aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2013-05-21 15:16:29 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2013-05-21 15:16:59 +0900
commitc198c0a82526292ed31a37ae837185f2e679e844 (patch)
treed5794b9406f9d9da5b8ce416a7e2a10d12ace67b
Initial commit
-rw-r--r--COPYING674
-rw-r--r--ChangeLog4
-rw-r--r--EXCEPTION11
-rw-r--r--board/board-fst-01.h20
-rw-r--r--board/board-stm8s-discovery.h16
-rw-r--r--chopstx.c813
-rw-r--r--chopstx.h88
-rw-r--r--chopstx.pngbin0 -> 16318 bytes
-rw-r--r--chopstx.svg156
-rw-r--r--entry.c340
-rw-r--r--example/Makefile31
-rw-r--r--example/aes-constant-ft.c145
-rw-r--r--example/sample.c138
-rw-r--r--example/sample.ld142
-rw-r--r--example/sys.c600
-rw-r--r--example/sys.h97
-rw-r--r--rules.mk51
17 files changed, 3326 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e8f77e2
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+2013-05-21 Niibe Yutaka <gniibe@fsij.org>
+
+ * Initial commit.
+
diff --git a/EXCEPTION b/EXCEPTION
new file mode 100644
index 0000000..1fb1de2
--- /dev/null
+++ b/EXCEPTION
@@ -0,0 +1,11 @@
+For released versions of Chopstx, it is OK to distribute a binary
+without the copy of the GNU GPL.
+
+Legally speaking:
+
+As additional permission under GNU GPL version 3 section 7, you may
+distribute non-source form of the code without the copy of the GNU GPL
+normally required by section 4, provided you accompany the license
+notice and a URL through which recipients can access the Corresponding
+Source.
+--
diff --git a/board/board-fst-01.h b/board/board-fst-01.h
new file mode 100644
index 0000000..c9ec367
--- /dev/null
+++ b/board/board-fst-01.h
@@ -0,0 +1,20 @@
+#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
+#define STM32_PLLMUL_VALUE 6
+#define STM32_HSECLK 12000000
+
+#define GPIO_USB_SET_TO_ENABLE 10
+#define GPIO_LED_SET_TO_EMIT 0
+
+#define VAL_GPIO_ODR 0xFFFFE7FD
+#define VAL_GPIO_CRL 0xBBB38888 /* PA7...PA0 */
+#define VAL_GPIO_CRH 0x88811388 /* PA15...PA8 */
+
+#define VAL_GPIO_LED_ODR 0xFFFFFFFF
+#define VAL_GPIO_LED_CRL 0x88888883 /* PA7...PA0 */
+#define VAL_GPIO_LED_CRH 0x88888888 /* PA15...PA8 */
+
+#define GPIO_USB_BASE GPIOA_BASE
+#define GPIO_LED_BASE GPIOB_BASE
+
+#define RCC_APB2ENR_IOP_EN (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN)
+#define RCC_APB2RSTR_IOP_RST (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST)
diff --git a/board/board-stm8s-discovery.h b/board/board-stm8s-discovery.h
new file mode 100644
index 0000000..6be488a
--- /dev/null
+++ b/board/board-stm8s-discovery.h
@@ -0,0 +1,16 @@
+#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
+#define STM32_PLLMUL_VALUE 9
+#define STM32_HSECLK 8000000
+
+#undef GPIO_USB_CLEAR_TO_ENABLE
+#define GPIO_LED_SET_TO_EMIT 8
+
+#define VAL_GPIO_ODR 0xFFFFE7FF
+#define VAL_GPIO_CRL 0x88888888 /* PA7...PA0 */
+#define VAL_GPIO_CRH 0x88811881 /* PA15...PA8 */
+
+#define GPIO_USB_BASE GPIOA_BASE
+#define GPIO_LED_BASE GPIOA_BASE
+
+#define RCC_APB2ENR_IOP_EN (RCC_APB2ENR_IOPAEN)
+#define RCC_APB2RSTR_IOP_RST (RCC_APB2RSTR_IOPARST)
diff --git a/chopstx.c b/chopstx.c
new file mode 100644
index 0000000..1c8a5a1
--- /dev/null
+++ b/chopstx.c
@@ -0,0 +1,813 @@
+/*
+ * chopstx.c - Threads and only threads.
+ *
+ * Copyright (C) 2013 Flying Stone Technology
+ * Author: NIIBE Yutaka <gniibe@fsij.org>
+ *
+ * This file is a part of Chopstx, a thread library for embedded.
+ *
+ * Chopstx 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.
+ *
+ * Chopstx is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A special exception to the GNU GPL may be applied for a specific
+ * case. See the file EXCEPTION for full details.
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <chopstx.h>
+
+/* RUNNING: the current thread. */
+struct chx_thread *running;
+
+/* Use this when we support round robin scheduling. */
+#define PREEMPTION_USEC (1000*MHZ) /* 1ms */
+
+/* Double linked list operations. */
+struct chx_dll {
+ struct chx_thread *next, *prev;
+};
+
+
+/* READY: priority queue. */
+struct chx_ready {
+ struct chx_thread *next, *prev;
+ struct chx_spinlock lock;
+};
+
+static struct chx_ready q_ready;
+
+struct chx_timer {
+ struct chx_thread *next, *prev;
+ struct chx_spinlock lock;
+};
+
+/* threads waiting for timer. */
+static struct chx_timer q_timer;
+
+/* XXX: q_exit; Queue for threads already exited. */
+
+/* Forward declaration(s). */
+static void chx_preempt (void);
+
+
+/**************/
+static void chx_LOCK (struct chx_spinlock *lk)
+{
+ (void)lk;
+}
+
+static void chx_UNLOCK (struct chx_spinlock *lk)
+{
+ (void)lk;
+}
+
+/* The thread context: specific to ARM Cortex-M3 now. */
+struct tcontext {
+ uint32_t reg[9]; /* r4, r5, r6, r7, r8, r9, r10, r11, r13 */
+};
+
+/* Saved registers on the stack. */
+struct chx_stack_regs {
+ uint32_t reg[8]; /* r0, r1, r2, r3, r12, lr, pc, xpsr */
+};
+
+/*
+ * Constants for ARM.
+ */
+#define REG_SP 8
+
+#define REG_R0 0
+#define REG_LR 5
+#define REG_PC 6
+#define REG_XPSR 7
+
+#define INITIAL_XPSR 0x01000000 /* T=1 */
+
+/*
+ * SysTick registers.
+ */
+static volatile uint32_t *const SYST_CSR = (uint32_t *const)0xE000E010;
+static volatile uint32_t *const SYST_RVR = (uint32_t *const)0xE000E014;
+static volatile uint32_t *const SYST_CVR = (uint32_t *const)0xE000E018;
+
+#define MHZ 72
+
+static uint32_t usec_to_ticks (uint32_t usec)
+{
+ return usec * MHZ;
+}
+/**************/
+
+struct chx_thread {
+ struct chx_thread *next, *prev;
+ struct tcontext tc;
+ uint16_t prio;
+ uint16_t prio_orig;
+ uint32_t v;
+ struct chx_mtx *mutex_list;
+} __attribute__((packed));
+
+
+/*
+ * Double linked list handling.
+ */
+
+static int
+ll_empty (void *head)
+{
+ struct chx_thread *l = (struct chx_thread *)head;
+
+ return (struct chx_thread *)l == l->next;
+}
+
+static struct chx_thread *
+ll_dequeue (struct chx_thread *tp)
+{
+ struct chx_thread *tp0 = tp;
+
+ tp->next->prev = tp->prev;
+ tp->prev->next = tp->next;
+ return tp0;
+}
+
+static void
+ll_insert (struct chx_thread *tp0, void *head)
+{
+ struct chx_thread *tp = (struct chx_thread *)head;
+
+ tp0->next = tp;
+ tp0->prev = tp->prev;
+ tp->prev->next = tp0;
+ tp->prev = tp0;
+}
+
+
+static struct chx_thread *
+ll_pop (void *head)
+{
+ struct chx_thread *l = (struct chx_thread *)head;
+ struct chx_thread *tp0 = l->next;
+
+ if (tp0 == l)
+ return NULL;
+
+ return ll_dequeue (tp0);
+}
+
+static void
+ll_prio_push (struct chx_thread *tp0, void *head)
+{
+ struct chx_thread *l = (struct chx_thread *)head;
+ struct chx_thread *tp;
+
+ for (tp = l->next; tp != l; tp = tp->next)
+ if (tp->prio <= tp0->prio)
+ break;
+
+ ll_insert (tp0, tp);
+}
+
+static void
+ll_prio_enqueue (struct chx_thread *tp0, void *head)
+{
+ struct chx_thread *l = (struct chx_thread *)head;
+ struct chx_thread *tp;
+
+ for (tp = l->next; tp != l; tp = tp->next)
+ if (tp->prio < tp0->prio)
+ break;
+
+ ll_insert (tp0, tp);
+}
+
+
+/*
+ * Thread status encoded in ->v.
+ */
+#define THREAD_WAIT_MTX 0x00000001
+#define THREAD_WAIT_CND 0x00000002
+#define THREAD_WAITTIME 0x00000003
+
+#define THREAD_RUNNING 0x00000000
+#define THREAD_WAIT_INT 0x00000004
+#define THREAD_EXITED 0x00000008
+#define THREAD_READY 0x0000000C
+
+static uint32_t
+chx_ready_pop (void)
+{
+ struct chx_thread *tp;
+
+ chx_LOCK (&q_ready.lock);
+ tp = ll_pop (&q_ready);
+ if (tp)
+ tp->v = THREAD_RUNNING;
+ chx_UNLOCK (&q_ready.lock);
+
+ return (uint32_t)tp;
+}
+
+
+static void
+chx_ready_push (struct chx_thread *t)
+{
+ chx_LOCK (&q_ready.lock);
+ t->v = THREAD_READY;
+ ll_prio_push (t, &q_ready);
+ chx_UNLOCK (&q_ready.lock);
+}
+
+
+static void
+chx_ready_enqueue (struct chx_thread *t)
+{
+ chx_LOCK (&q_ready.lock);
+ t->v = THREAD_READY;
+ ll_prio_enqueue (t, &q_ready);
+ chx_UNLOCK (&q_ready.lock);
+}
+
+/* Registers on stack (PSP): r0, r1, r2, r3, r12, lr, pc, xpsr */
+static void __attribute__ ((naked,used))
+sched (void)
+{
+ register uint32_t r0 asm ("r0");
+
+ asm volatile ("cpsid i" : : : "memory");
+
+ r0 = chx_ready_pop ();
+
+ asm volatile (/* Now, r0 points to the thread to be switched. */
+ /* Put it to *running. */
+ "ldr r1, =running\n\t"
+ /* Update running. */
+ "str r0, [r1]\n\t"
+ "cbz r0, 3f\n\t"
+ /**/
+ "str r0, [r0]\n\t"
+ "str r0, [r0, 4]\n\t"
+ "cpsie i\n\t" /* Unmask interrupts. */
+ "add r0, #8\n\t"
+ "ldm r0!, {r4, r5, r6, r7}\n\t"
+ "ldr r8, [r0], 4\n\t"
+ "ldr r9, [r0], 4\n\t"
+ "ldr r10, [r0], 4\n\t"
+ "ldr r11, [r0], 4\n\t"
+ "ldr r1, [r0]\n\t"
+ "msr PSP, r1\n\t"
+ "mov r0, #-1\n\t"
+ "sub r0, #2\n\t" /* EXC_RETURN to a thread with PSP */
+ "bx r0\n"
+ "3:\n\t"
+ "cpsie i\n\t" /* Unmask interrupts. */
+ /* Spawn an IDLE thread. */
+ "ldr r0, =__main_stack_end__\n\t"
+ "msr MSP, r0\n\t"
+ "mov r0, #0\n\t"
+ "mov r1, #0\n\t"
+ "ldr r2, =idle\n\t" /* PC = idle */
+ "mov r3, #0x01000000\n\t" /* xPSR = T-flag set (Thumb) */
+ "push {r0, r1, r2, r3}\n\t"
+ "mov r0, #0\n\t"
+ "mov r1, #0\n\t"
+ "mov r2, #0\n\t"
+ "mov r3, #0\n\t"
+ "push {r0, r1, r2, r3}\n"
+ "mov r0, #-1\n\t"
+ "sub r0, #6\n\t" /* EXC_RETURN to a thread with MSP */
+ "bx r0\n"
+ : /* no output */ : "r" (r0) : "memory");
+}
+
+void __attribute__ ((naked))
+preempt (void)
+{
+ register uint32_t r0 asm ("r0");
+
+ asm volatile ("ldr r1, =running\n\t"
+ "ldr r0, [r1]\n\t"
+ "cbnz r0, 0f\n\t"
+ /* It's idle which was preempted. */
+ "ldr r1, =__main_stack_end__\n\t"
+ "msr MSP, r1\n\t"
+ "b sched\n"
+ "0:\n\t"
+ "ldr r2, [r0, 48]\n\t" /* Check ->v to avoid RACE. */
+ "cbz r2, 1f\n\t"
+ /* RUNNING is busy on transition, do nothing. */
+ "bx lr\n"
+ "1:\n\t"
+ "add r2, r0, #8\n\t"
+ /* Save registers onto CHX_THREAD struct. */
+ "stm r2!, {r4, r5, r6, r7}\n\t"
+ "mov r3, r8\n\t"
+ "mov r4, r9\n\t"
+ "mov r5, r10\n\t"
+ "mov r6, r11\n\t"
+ "mrs r7, PSP\n\t" /* r13(=SP) in user space. */
+ "stm r2, {r3, r4, r5, r6, r7}"
+ : "=r" (r0): /* no input */ : "memory");
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_ready_push ((struct chx_thread *)r0);
+ asm volatile ("ldr r1, =running\n\t"
+ "mov r2, #0\n\t"
+ "str r2, [r1]\n\t" /* running := NULL */
+ "cpsie i" /* Unmask interrupts. */
+ : /* no output */ : /* no input */ : "memory");
+
+ asm volatile ("b sched"
+ : /* no output */: /* no input */ : "memory");
+}
+
+
+/* system call: sched */
+void __attribute__ ((naked))
+svc (void)
+{
+ register uint32_t r0 asm ("r0");
+ register uint32_t orig_r0 asm ("r2");
+
+ asm volatile ("ldr r1, =running\n\t"
+ "ldr r0, [r1]\n\t"
+ "add r2, r0, #8\n\t"
+ /* Save registers onto CHX_THREAD struct. */
+ "stm r2!, {r4, r5, r6, r7}\n\t"
+ "mov r3, r8\n\t"
+ "mov r4, r9\n\t"
+ "mov r5, r10\n\t"
+ "mov r6, r11\n\t"
+ "mrs r7, PSP\n\t" /* r13(=SP) in user space. */
+ "stm r2, {r3, r4, r5, r6, r7}\n\t"
+ "ldr r2, [r7]"
+ : "=r" (r0), "=r" (orig_r0) : /* no input */ : "memory");
+
+ if (orig_r0)
+ {
+ asm volatile ("cpsid i" : : : "memory");
+ chx_ready_enqueue ((struct chx_thread *)r0);
+ asm volatile ("ldr r1, =running\n\t"
+ "mov r2, #0\n\t"
+ "str r2, [r1]\n\t" /* running := NULL */
+ "cpsie i" /* Unmask interrupts. */
+ : /* no output */ : /* no input */ : "memory");
+ }
+
+ asm volatile ("b sched"
+ : /* no output */: /* no input */ : "memory");
+}
+
+
+static void
+chx_set_timer (struct chx_thread *q, uint32_t ticks)
+{
+ if (q == (struct chx_thread *)&q_timer)
+ {
+ *SYST_RVR = ticks;
+ *SYST_CVR = 0; /* write (any) to clear the counter to reload. */
+ *SYST_RVR = 0;
+ }
+ else
+ q->v = (ticks<<8)|THREAD_WAITTIME;
+}
+
+static void
+chx_timer_insert (struct chx_thread *tp, uint32_t usec)
+{
+ uint32_t ticks = usec_to_ticks (usec);
+ uint32_t next_ticks = *SYST_CVR;
+ struct chx_thread *q;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&q_timer.lock);
+
+ for (q = q_timer.next; q != (struct chx_thread *)&q_timer; q = q->next)
+ {
+ if (ticks < next_ticks)
+ {
+ ll_insert (tp, q);
+ chx_set_timer (tp->prev, ticks);
+ chx_set_timer (tp, (next_ticks - ticks));
+ break;
+ }
+ else
+ {
+ ticks -= next_ticks;
+ next_ticks = (q->v >> 8);
+ }
+ }
+
+ if (q == (struct chx_thread *)&q_timer)
+ {
+ ll_insert (tp, q);
+ chx_set_timer (tp->prev, ticks);
+ chx_set_timer (tp, 1); /* Non-zero for the last entry. */
+ }
+ chx_UNLOCK (&q_timer.lock);
+ asm volatile ("cpsie i" : : : "memory");
+}
+
+
+void
+chx_timer_expired (void)
+{
+ struct chx_thread *t;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&q_timer.lock);
+ if ((t = ll_pop (&q_timer)))
+ {
+ uint32_t next_tick = t->v >> 8;
+
+ chx_ready_enqueue (t);
+
+ if (!ll_empty (&q_timer))
+ {
+ struct chx_thread *t_next;
+
+ for (t = q_timer.next;
+ t != (struct chx_thread *)&q_timer && next_tick == 0;
+ t = t_next)
+ {
+ next_tick = (t->v >> 8);
+ t_next = t->next;
+ ll_dequeue (t);
+ chx_ready_enqueue (t);
+ }
+
+ if (!ll_empty (&q_timer))
+ chx_set_timer ((struct chx_thread *)&q_timer, next_tick);
+ }
+ }
+
+ chx_preempt ();
+ chx_UNLOCK (&q_timer.lock);
+ asm volatile ("cpsie i" : : : "memory");
+}
+
+
+static void
+chx_enable_intr (uint8_t irq_num)
+{
+}
+
+static void
+chx_disable_intr (uint8_t irq_num)
+{
+}
+
+void
+chx_handle_intr (chopstix_intr_t *intr)
+{
+ chx_disable_intr (intr->irq_num);
+ asm volatile ("cpsid i" : : : "memory");
+ intr->ready++;
+ if (intr->t)
+ {
+ chx_ready_enqueue (intr->t);
+ chx_preempt ();
+ }
+ asm volatile ("cpsie i" : : : "memory");
+}
+
+void
+chx_systick_init (void)
+{
+ *SYST_RVR = 0;
+ *SYST_CVR = 0;
+ *SYST_CSR = 7;
+}
+
+#define PRIO_DEFAULT 1
+
+void
+chx_init (struct chx_thread *tp)
+{
+ memset (&tp->tc, 0, sizeof (tp->tc));
+ q_ready.next = q_ready.prev = (struct chx_thread *)&q_ready;
+ q_timer.next = q_timer.prev = (struct chx_thread *)&q_timer;
+ tp->prio_orig = tp->prio = PRIO_DEFAULT;
+ tp->next = tp->prev = tp;
+ tp->mutex_list = NULL;
+ tp->v = THREAD_RUNNING;
+
+ running = tp;
+}
+
+
+static void
+chx_preempt (void)
+{
+ static volatile uint32_t *const ICSR = (uint32_t *const)0xE000ED04;
+
+ *ICSR = (1 << 28);
+ asm volatile ("" : : : "memory");
+}
+
+static void
+chx_sched (void)
+{
+ register uint32_t r0 asm ("r0") = 0;
+
+ asm volatile ("svc #0" : : "r" (r0) : "memory");
+}
+
+static void
+chx_yield (void)
+{
+ register uint32_t r0 asm ("r0") = 1;
+
+ asm volatile ("svc #0" : : "r" (r0) : "memory");
+}
+
+void
+chopstx_attr_init (chopstx_attr_t *attr)
+{
+ attr->prio = PRIO_DEFAULT;
+ attr->addr = 0;
+ attr->size = 0;
+}
+
+void
+chopstx_attr_setschedparam (chopstx_attr_t *attr, uint8_t prio)
+{
+ attr->prio = prio;
+}
+
+void
+chopstx_attr_setstack (chopstx_attr_t *attr, uint32_t addr, size_t size)
+{
+ attr->addr = addr;
+ attr->size = size;
+}
+
+void
+chopstx_create (chopstx_t *thd, const chopstx_attr_t *attr,
+ void *(thread_entry) (void *), void *arg)
+{
+ struct chx_thread *tp;
+ void *stack;
+ struct chx_stack_regs *p;
+
+ if (attr->size < sizeof (struct chx_thread) + 8 * sizeof (uint32_t))
+ return;
+
+ stack = (void *)(attr->addr + attr->size - sizeof (struct chx_thread)
+ - sizeof (struct chx_stack_regs));
+ memset (stack, 0, sizeof (struct chx_stack_regs));
+ p = (struct chx_stack_regs *)stack;
+ p->reg[REG_R0] = (uint32_t)arg;
+ p->reg[REG_LR] = 0; /* XXX: address of exit??? */
+ p->reg[REG_PC] = (uint32_t)thread_entry;
+ p->reg[REG_XPSR] = INITIAL_XPSR;
+
+ tp = (struct chx_thread *)(stack + sizeof (struct chx_stack_regs));
+ memset (&tp->tc, 0, sizeof (tp->tc));
+ tp->prio_orig = tp->prio = attr->prio;
+ tp->tc.reg[REG_SP] = (uint32_t)stack;
+ tp->next = tp->prev = tp;
+ tp->mutex_list = NULL;
+ tp->v = THREAD_EXITED;
+ *thd = (uint32_t)tp;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_ready_enqueue (tp);
+ asm volatile ("cpsie i" : : : "memory");
+ if (tp->prio > running->prio)
+ chx_yield ();
+}
+
+
+void
+chopstx_usleep (uint32_t usec)
+{
+ while (usec)
+ {
+ uint32_t usec0 = (usec > 200*1000) ? 200*1000: usec;
+
+ chx_timer_insert (running, usec0);
+ chx_sched ();
+
+ usec -= usec0;
+ }
+}
+
+
+void
+chopstx_mutex_init (chopstx_mutex_t *mutex)
+{
+ mutex->q.next = mutex->q.prev = (struct chx_thread *)mutex;
+ mutex->list = NULL;
+}
+
+void
+chopstx_mutex_lock (chopstx_mutex_t *mutex)
+{
+ while (1)
+ {
+ struct chx_thread *t = running;
+ chopstx_mutex_t *m;
+ struct chx_thread *owner;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&mutex->lock);
+ if (mutex->owner == NULL)
+ {
+ /* The mutex is acquired. */
+ mutex->owner = t;
+ mutex->list = t->mutex_list;
+ t->mutex_list = mutex;
+ chx_UNLOCK (&mutex->lock);
+ asm volatile ("cpsie i" : : : "memory");
+ return;
+ }
+
+ m = mutex;
+ owner = m->owner;
+ while (1)
+ {
+ owner->prio = t->prio;
+ if (owner->v == THREAD_READY)
+ {
+ ll_prio_enqueue (ll_dequeue (owner), &q_ready);
+ break;
+ }
+ else if ((owner->v & 0x03) == THREAD_WAIT_MTX)
+ {
+ m = (chopstx_mutex_t *)(owner->v & ~0x03);
+
+ ll_prio_enqueue (ll_dequeue (owner), m);
+ owner = m->owner;
+ continue;
+ }
+ else if ((owner->v & 0x03) == THREAD_WAIT_CND)
+ {
+ chopstx_cond_t *cnd = (chopstx_cond_t *)(owner->v & ~0x03);
+
+ ll_prio_enqueue (ll_dequeue (owner), cnd);
+ break;
+ }
+ else
+ break;
+ /* XXX: RUNNING and SMP??? */
+ }
+
+ ll_prio_enqueue (t, &mutex->q);
+ t->v = (uint32_t)mutex | THREAD_WAIT_MTX;
+ chx_UNLOCK (&mutex->lock);
+ asm volatile ("cpsie i" : : : "memory");
+ chx_sched ();
+ }
+}
+
+void
+chopstx_mutex_unlock (chopstx_mutex_t *mutex)
+{
+ struct chx_thread *t;
+ int yield = 0;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&mutex->lock);
+ mutex->owner = NULL;
+ running->mutex_list = mutex->list;
+ mutex->list = NULL;
+
+ t = ll_pop (&mutex->q);
+ if (t)
+ {
+ uint16_t newprio = running->prio_orig;
+ chopstx_mutex_t *m;
+
+ chx_ready_enqueue (t);
+
+ /* Examine mutexes we hold, and determine new priority for running. */
+ for (m = running->mutex_list; m; m = m->list)
+ if (!ll_empty (&m->q) && m->q.next->prio > newprio)
+ newprio = m->q.next->prio;
+ /* Then, assign it. */
+ running->prio = newprio;
+
+ if (t->prio > running->prio)
+ yield = 1;
+ }
+
+ chx_UNLOCK (&mutex->lock);
+ asm volatile ("cpsie i" : : : "memory");
+ if (yield)
+ chx_yield ();
+}
+
+
+void
+chopstx_cond_init (chopstx_cond_t *cond)
+{
+ cond->q.next = cond->q.prev = (struct chx_thread *)cond;
+}
+
+void
+chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex)
+{
+ struct chx_thread *t = running;
+
+ if (mutex)
+ chopstx_mutex_unlock (mutex);
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&cond->lock);
+ ll_prio_enqueue (t, &cond->q);
+ t->v = (uint32_t)cond | THREAD_WAIT_CND;
+ chx_UNLOCK (&cond->lock);
+ asm volatile ("cpsie i" : : : "memory");
+
+ chx_sched ();
+
+ if (mutex)
+ chopstx_mutex_lock (mutex);
+}
+
+void
+chopstx_cond_signal (chopstx_cond_t *cond)
+{
+ struct chx_thread *t;
+ int yield = 0;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&cond->lock);
+ t = ll_pop (&cond->q);
+ if (t)
+ {
+ chx_ready_enqueue (t);
+ if (t->prio > running->prio)
+ yield = 1;
+ }
+ chx_UNLOCK (&cond->lock);
+ asm volatile ("cpsie i" : : : "memory");
+
+ if (yield)
+ chx_yield ();
+}
+
+void
+chopstx_cond_broadcast (chopstx_cond_t *cond)
+{
+ struct chx_thread *t;
+ int yield = 1;
+
+ asm volatile ("cpsid i" : : : "memory");
+ chx_LOCK (&cond->lock);
+ while ((t = ll_pop (&cond->q)))
+ {
+ chx_ready_enqueue (t);
+ if (t->prio > running->prio)
+ yield = 1;
+ }
+ chx_UNLOCK (&cond->lock);
+ asm volatile ("cpsie i" : : : "memory");
+ if (yield)
+ chx_yield ();
+}
+
+
+#define MAX_INTR_NUM 16
+
+chopstix_intr_t *intr_table[MAX_INTR_NUM];
+
+void
+chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num)
+{
+ intr_table[irq_num] = intr;
+ intr->irq_num = irq_num;
+ intr->t = running;
+ intr->ready = 0;
+}
+
+
+void
+chopstx_wait_intr (chopstix_intr_t *intr)
+{
+ chx_enable_intr (intr->irq_num);
+ asm volatile ("cpsid i" : : : "memory");
+ while (intr->ready == 0)
+ {
+ intr->t = running;
+ running->v = THREAD_WAIT_INT;
+ asm volatile ("cpsie i" : : : "memory");
+ chx_sched ();
+ asm volatile ("cpsid i" : : : "memory");
+ }
+ intr->ready--;
+ asm volatile ("cpsie i" : : : "memory");
+}
diff --git a/chopstx.h b/chopstx.h
new file mode 100644
index 0000000..6ab9b87
--- /dev/null
+++ b/chopstx.h
@@ -0,0 +1,88 @@
+/*
+ * chopstx.h - Threads and only threads.
+ *
+ * Copyright (C) 2013 Flying Stone Technology
+ * Author: NIIBE Yutaka <gniibe@fsij.org>
+ *
+ * This file is a part of Chopstx, a thread library for embedded.
+ *
+ * Chopstx 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.
+ *
+ * Chopstx is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A special exception to the GNU GPL may be applied for a specific
+ * case. See the file EXCEPTION for full details.
+ *
+ */
+
+typedef uint32_t chopstx_t;
+struct struct_attr { uint32_t prio; uint32_t addr; size_t size; };
+typedef struct struct_attr chopstx_attr_t;
+
+void chopstx_attr_init (chopstx_attr_t *attr);
+
+/* NOTE: This signature is different to PTHREAD's one. */
+void chopstx_attr_setschedparam (chopstx_attr_t *attr, uint8_t prio);
+
+void chopstx_attr_setstack (chopstx_attr_t *attr, uint32_t addr,
+ size_t size);
+
+void chopstx_create (chopstx_t *thd, const chopstx_attr_t *attr,
+ void *(thread_entry) (void *), void *);
+
+void chopstx_usleep (uint32_t useconds);
+
+struct chx_spinlock {
+ /* nothing for uniprocessor. */
+};
+
+typedef uint16_t chopstx_prio_t;
+typedef struct chx_mtx {
+ struct {
+ struct chx_thread *next, *prev;
+ } q;
+ struct chx_spinlock lock;
+ struct chx_thread *owner;
+ struct chx_mtx *list;
+} chopstx_mutex_t;
+
+/* NOTE: This signature is different to PTHREAD's one. */
+void chopstx_mutex_init (chopstx_mutex_t *mutex);
+
+void chopstx_mutex_lock (chopstx_mutex_t *mutex);
+
+void chopstx_mutex_unlock (chopstx_mutex_t *mutex);
+
+typedef struct chx_cond {
+ struct {
+ struct chx_thread *next, *prev;
+ } q;
+ struct chx_spinlock lock;
+} chopstx_cond_t;
+
+/* NOTE: This signature is different to PTHREAD's one. */
+void chopstx_cond_init (chopstx_cond_t *cond);
+
+void chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex);
+void chopstx_cond_signal (chopstx_cond_t *cond);
+void chopstx_cond_broadcast (chopstx_cond_t *cond);
+
+typedef struct chx_intr {
+ struct chx_thread *t;
+ struct chx_spinlock lock;
+ uint8_t irq_num;
+ uint8_t ready;
+} chopstix_intr_t;
+
+void chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num);
+
+void chopstx_wait_intr (chopstix_intr_t *intr);
diff --git a/chopstx.png b/chopstx.png
new file mode 100644
index 0000000..5335dcc
--- /dev/null
+++ b/chopstx.png
Binary files differ
diff --git a/chopstx.svg b/chopstx.svg
new file mode 100644
index 0000000..61ab6ae
--- /dev/null
+++ b/chopstx.svg
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="chopstx.svg"
+ inkscape:export-filename="chopstx.png"
+ inkscape:export-xdpi="36"
+ inkscape:export-ydpi="36">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path3762"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.5"
+ inkscape:cx="459.21448"
+ inkscape:cy="471.91176"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ showborder="true"
+ inkscape:window-width="906"
+ inkscape:window-height="719"
+ inkscape:window-x="1"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g4305"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <g
+ transform="translate(-190,-14)"
+ id="g4236"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <g
+ id="g4199"
+ transform="translate(186,0)"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ style="fill-rule:evenodd;stroke:none;stroke-width:0.10000000000000001;fill:#164122;fill-opacity:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 245.5395,924.99188 237.95004,940.17081 274,915.50504 l -43.63943,1.89737 z"
+ id="path4205"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#164122;fill-opacity:1;stroke:none;stroke-width:0.10000000000000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 451.30156,863.09375 c -12.29154,0.67964 -24.56513,6.31983 -32.55093,15.74368 -6.74505,8.98414 -14.74647,19.18713 -13.27855,31.13292 0.81861,7.53179 4.96334,15.52377 12.3578,18.2841 6.5527,1.56145 12.36737,-2.87335 18.24105,-4.87414 2.46026,0.0325 7.79766,-5.57819 2.80659,-2.62717 -5.86212,3.04634 -12.09693,7.41598 -19.02815,6.20781 -6.67881,-2.45807 -10.67091,-9.57389 -11.94134,-16.2776 -1.65616,-6.85973 1.2677,-13.63117 5.02324,-19.23708 7.11677,-11.84162 18.63914,-21.98251 32.76069,-23.75581 14.13711,-2.23575 29.01952,1.81411 40.58636,10.08551 7.52021,5.28929 14.01916,12.81867 15.41858,22.18896 2.35212,12.95802 -5.71873,25.02827 -15.27391,32.93766 -9.57979,7.75126 -20.98736,12.8445 -32.4632,17.09918 -5.28833,-0.64073 -7.07207,5.94812 -4.23041,9.49281 0.54847,2.21012 1.09694,4.42025 1.64541,6.63037 18.79336,-6.7629 38.15989,-16.2698 49.24661,-33.6521 6.02058,-10.72278 10.41044,-23.35707 8.15467,-35.76217 -1.2356,-5.99366 -5.54747,-10.6846 -8.85242,-15.6466 -7.03785,-9.20338 -18.12594,-14.19792 -29.30714,-16.17859 -6.35088,-1.24159 -12.83528,-2.02773 -19.31495,-1.79174 z"
+ id="path4214"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g4236-1"
+ transform="translate(-297.33681,-120.22628)"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <g
+ id="g4199-2"
+ transform="translate(186,0)"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ style="fill-rule:evenodd;stroke:none;stroke-width:0.10000000000000001;fill:#164122;fill-opacity:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 245.5395,924.99188 237.95004,940.17081 274,915.50504 l -43.63943,1.89737 z"
+ id="path4205-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#164122;fill-opacity:1;stroke:none;stroke-width:0.10000000000000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 451.30156,863.09375 c -12.29154,0.67964 -24.56513,6.31983 -32.55093,15.74368 -6.74505,8.98414 -14.74647,19.18713 -13.27855,31.13292 0.81861,7.53179 4.96334,15.52377 12.3578,18.2841 6.5527,1.56145 12.36737,-2.87335 18.24105,-4.87414 2.46026,0.0325 7.79766,-5.57819 2.80659,-2.62717 -5.86212,3.04634 -12.09693,7.41598 -19.02815,6.20781 -6.67881,-2.45807 -10.67091,-9.57389 -11.94134,-16.2776 -1.65616,-6.85973 1.2677,-13.63117 5.02324,-19.23708 7.11677,-11.84162 18.63914,-21.98251 32.76069,-23.75581 14.13711,-2.23575 29.01952,1.81411 40.58636,10.08551 7.52021,5.28929 14.01916,12.81867 15.41858,22.18896 2.35212,12.95802 -5.71873,25.02827 -15.27391,32.93766 -9.57979,7.75126 -20.98736,12.8445 -32.4632,17.09918 -5.28833,-0.64073 -7.07207,5.94812 -4.23041,9.49281 0.54847,2.21012 1.09694,4.42025 1.64541,6.63037 18.79336,-6.7629 38.15989,-16.2698 49.24661,-33.6521 6.02058,-10.72278 10.41044,-23.35707 8.15467,-35.76217 -1.2356,-5.99366 -5.54747,-10.6846 -8.85242,-15.6466 -7.03785,-9.20338 -18.12594,-14.19792 -29.30714,-16.17859 -6.35088,-1.24159 -12.83528,-2.02773 -19.31495,-1.79174 z"
+ id="path4214-1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g4236-8"
+ transform="translate(-321.33681,5.77372)"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <g
+ id="g4199-5"
+ transform="translate(186,0)"
+ style="fill:#164122;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:0.10000000000000001;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ style="fill-rule:evenodd;stroke:none;stroke-width:0.10000000000000001;fill:#164122;fill-opacity:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 245.5395,924.99188 237.95004,940.17081 274,915.50504 l -43.63943,1.89737 z"
+ id="path4205-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#164122;fill-opacity:1;stroke:none;stroke-width:0.10000000000000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 451.30156,863.09375 c -12.29154,0.67964 -24.56513,6.31983 -32.55093,15.74368 -6.74505,8.98414 -14.74647,19.18713 -13.27855,31.13292 0.81861,7.53179 4.96334,15.52377 12.3578,18.2841 6.5527,1.56145 12.36737,-2.87335 18.24105,-4.87414 2.46026,0.0325 7.79766,-5.57819 2.80659,-2.62717 -5.86212,3.04634 -12.09693,7.41598 -19.02815,6.20781 -6.67881,-2.45807 -10.67091,-9.57389 -11.94134,-16.2776 -1.65616,-6.85973 1.2677,-13.63117 5.02324,-19.23708 7.11677,-11.84162 18.63914,-21.98251 32.76069,-23.75581 14.13711,-2.23575 29.01952,1.81411 40.58636,10.08551 7.52021,5.28929 14.01916,12.81867 15.41858,22.18896 2.35212,12.95802 -5.71873,25.02827 -15.27391,32.93766 -9.57979,7.75126 -20.98736,12.8445 -32.4632,17.09918 -5.28833,-0.64073 -7.07207,5.94812 -4.23041,9.49281 0.54847,2.21012 1.09694,4.42025 1.64541,6.63037 18.79336,-6.7629 38.15989,-16.2698 49.24661,-33.6521 6.02058,-10.72278 10.41044,-23.35707 8.15467,-35.76217 -1.2356,-5.99366 -5.54747,-10.6846 -8.85242,-15.6466 -7.03785,-9.20338 -18.12594,-14.19792 -29.30714,-16.17859 -6.35088,-1.24159 -12.83528,-2.02773 -19.31495,-1.79174 z"
+ id="path4214-3"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g4301"
+ transform="translate(8,-22)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0"
+ id="path4281"
+ d="m 544,310.36218 -309,554 3,3 327,-545 -1,-14 z"
+ style="fill:#cd0000;fill-opacity:1;stroke:#000088;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0"
+ id="path4281-5"
+ d="m 478.99332,286.67888 -275.00872,571.63555 3.17555,2.81352 293.51899,-563.73807 -1.84294,-13.91415 z"
+ style="fill:#cd0000;fill-opacity:1;stroke:#000088;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+</svg>
diff --git a/entry.c b/entry.c
new file mode 100644
index 0000000..d82063d
--- /dev/null
+++ b/entry.c
@@ -0,0 +1,340 @@
+/*
+ * entry.c - Entry routine when reset and interrupt vectors.
+ *
+ * Copyright (C) 2013 Flying Stone Technology
+ * Author: NIIBE Yutaka <gniibe@fsij.org>
+ *
+ * This file is a part of Chopstx, a thread library for embedded.
+ *
+ * Chopstx 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.
+ *
+ * Chopstx is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A special exception to the GNU GPL may be applied for a specific
+ * case. See the file EXCEPTION for full details.
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "sys.h"
+
+static void __attribute__ ((used))
+flash_unlock (void)
+{
+ (*vector[3]) ();
+}
+
+#if 0
+static void __attribute__ ((used))
+clock_init (void)
+{
+ (*vector[16]) ();
+}
+
+static void __attribute__ ((used))
+gpio_init (void)
+{
+ (*vector[17]) ();
+}
+#else
+#include "board.h"
+
+#define STM32_SW_PLL (2 << 0)
+#define STM32_PLLSRC_HSE (1 << 16)
+
+#define STM32_PLLXTPRE_DIV1 (0 << 17)
+#define STM32_PLLXTPRE_DIV2 (1 << 17)
+
+#define STM32_HPRE_DIV1 (0 << 4)
+
+#define STM32_PPRE1_DIV2 (4 << 8)
+
+#define STM32_PPRE2_DIV1 (0 << 11)
+#define STM32_PPRE2_DIV2 (4 << 11)
+
+#define STM32_ADCPRE_DIV4 (1 << 14)
+#define STM32_ADCPRE_DIV6 (2 << 14)
+
+#define STM32_USBPRE_DIV1P5 (0 << 22)
+
+#define STM32_MCO_NOCLOCK (0 << 24)
+
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV2
+#define STM32_PPRE2 STM32_PPRE2_DIV1
+#define STM32_ADCPRE STM32_ADCPRE_DIV6
+#define STM32_MCOSEL STM32_MCO_NOCLOCK
+#define STM32_USBPRE STM32_USBPRE_DIV1P5
+
+#define STM32_PLLCLKIN (STM32_HSECLK / 1)
+#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18)
+#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)
+#define STM32_SYSCLK STM32_PLLCLKOUT
+#define STM32_HCLK (STM32_SYSCLK / 1)
+
+#define STM32_FLASHBITS 0x00000012
+
+#define PERIPH_BASE 0x40000000
+#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
+#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
+
+struct RCC {
+ volatile uint32_t CR;
+ volatile uint32_t CFGR;
+ volatile uint32_t CIR;
+ volatile uint32_t APB2RSTR;
+ volatile uint32_t APB1RSTR;
+ volatile uint32_t AHBENR;
+ volatile uint32_t APB2ENR;
+ volatile uint32_t APB1ENR;
+ volatile uint32_t BDCR;
+ volatile uint32_t CSR;
+};
+
+#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
+#define RCC ((struct RCC *)RCC_BASE)
+
+#define RCC_APB1ENR_USBEN 0x00800000
+#define RCC_APB1RSTR_USBRST 0x00800000
+
+#define RCC_CR_HSION 0x00000001
+#define RCC_CR_HSIRDY 0x00000002
+#define RCC_CR_HSITRIM 0x000000F8
+#define RCC_CR_HSEON 0x00010000
+#define RCC_CR_HSERDY 0x00020000
+#define RCC_CR_PLLON 0x01000000
+#define RCC_CR_PLLRDY 0x02000000
+
+#define RCC_CFGR_SWS 0x0000000C
+#define RCC_CFGR_SWS_HSI 0x00000000
+
+#define RCC_AHBENR_CRCEN 0x0040
+
+struct FLASH {
+ volatile uint32_t ACR;
+ volatile uint32_t KEYR;
+ volatile uint32_t OPTKEYR;
+ volatile uint32_t SR;
+ volatile uint32_t CR;
+ volatile uint32_t AR;
+ volatile uint32_t RESERVED;
+ volatile uint32_t OBR;
+ volatile uint32_t WRPR;
+};
+
+#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000)
+#define FLASH ((struct FLASH *) FLASH_R_BASE)
+
+static void __attribute__((used))
+clock_init (void)
+{
+ /* HSI setup */
+ RCC->CR |= RCC_CR_HSION;
+ while (!(RCC->CR & RCC_CR_HSIRDY))
+ ;
+ RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION;
+ RCC->CFGR = 0;
+ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
+ ;
+
+ /* HSE setup */
+ RCC->CR |= RCC_CR_HSEON;
+ while (!(RCC->CR & RCC_CR_HSERDY))
+ ;
+
+ /* PLL setup */
+ RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC;
+ RCC->CR |= RCC_CR_PLLON;
+ while (!(RCC->CR & RCC_CR_PLLRDY))
+ ;
+
+ /* Clock settings */
+ RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE
+ | STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
+
+ /* Flash setup */
+ FLASH->ACR = STM32_FLASHBITS;
+
+ /* CRC */
+ RCC->AHBENR |= RCC_AHBENR_CRCEN;
+
+ /* Switching on the configured clock source. */
+ RCC->CFGR |= STM32_SW;
+ while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
+ ;
+}
+
+#define RCC_APB2ENR_IOPAEN 0x00000004
+#define RCC_APB2RSTR_IOPARST 0x00000004
+#define RCC_APB2ENR_IOPBEN 0x00000008
+#define RCC_APB2RSTR_IOPBRST 0x00000008
+#define RCC_APB2ENR_IOPCEN 0x00000010
+#define RCC_APB2RSTR_IOPCRST 0x00000010
+#define RCC_APB2ENR_IOPDEN 0x00000020
+#define RCC_APB2RSTR_IOPDRST 0x00000020
+
+
+struct GPIO {
+ volatile uint32_t CRL;
+ volatile uint32_t CRH;
+ volatile uint32_t IDR;
+ volatile uint32_t ODR;
+ volatile uint32_t BSRR;
+ volatile uint32_t BRR;
+ volatile uint32_t LCKR;
+};
+
+#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
+#define GPIOA ((struct GPIO *) GPIOA_BASE)
+#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
+#define GPIOB ((struct GPIO *) GPIOB_BASE)
+#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
+#define GPIOC ((struct GPIO *) GPIOC_BASE)
+#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
+#define GPIOD ((struct GPIO *) GPIOD_BASE)
+#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
+#define GPIOE ((struct GPIO *) GPIOE_BASE)
+
+#define GPIO_USB ((struct GPIO *) GPIO_USB_BASE)
+#define GPIO_LED ((struct GPIO *) GPIO_LED_BASE)
+
+static void __attribute__((used))
+gpio_init (void)
+{
+ /* Enable GPIO clock. */
+ RCC->APB2ENR |= RCC_APB2ENR_IOP_EN;
+ RCC->APB2RSTR = RCC_APB2RSTR_IOP_RST;
+ RCC->APB2RSTR = 0;
+
+ GPIO_USB->ODR = VAL_GPIO_ODR;
+ GPIO_USB->CRH = VAL_GPIO_CRH;
+ GPIO_USB->CRL = VAL_GPIO_CRL;
+
+#if GPIO_USB_BASE != GPIO_LED_BASE
+ GPIO_LED->ODR = VAL_GPIO_LED_ODR;
+ GPIO_LED->CRH = VAL_GPIO_LED_CRH;
+ GPIO_LED->CRL = VAL_GPIO_LED_CRL;
+#endif
+}
+#endif
+
+
+static void nmi (void)
+{
+ for (;;);
+}
+
+static void hard_fault (void)
+{
+ for (;;);
+}
+
+static void mem_manage (void)
+{
+ for (;;);
+}
+
+static void bus_fault (void)
+{
+ for (;;);
+}
+
+static void usage_fault (void)
+{
+ for (;;);
+}
+
+static void none (void)
+{
+}
+
+/*
+ * This routine only changes PSP and not MSP.
+ */
+static __attribute__ ((naked,section(".text.startup.0")))
+void entry (void)
+{
+ asm volatile ("bl clock_init\n\t"
+ /* Clear BSS. Assume its size is > 0. */
+ "mov r0, #0\n\t"
+ "ldr r1, =_bss_start\n\t"
+ "ldr r2, =_bss_end\n"
+ "0:\n\t"
+ "str r0, [r1], #4\n\t"
+ "cmp r2, r1\n\t"
+ "bhi 0b\n\t"
+ /* Switch to PSP. */
+ "ldr r0, =__process0_stack_end__\n\t"
+ "sub r0, #56\n\t"
+ "msr PSP, r0\n\t" /* Process (main routine) stack */
+ "mov r1, #2\n\t"
+ "msr CONTROL, r1\n\t"
+ "isb\n\t"
+ "bl chx_init\n\t"
+ "bl chx_systick_init\n\t"
+ "bl gpio_init\n\t"
+ /* Enable interrupts. */
+ "mov r0, #0\n\t"
+ "msr BASEPRI, r0\n\t"
+ "cpsie i\n\t"
+ /* Call main. */
+ "mov r1, r0\n\t"
+ "bl main\n"
+ "1:\n\t"
+ "b 1b"
+ : /* no output */ : /* no input */ : "memory");
+}
+
+void __attribute__((naked, used))
+idle (void)
+{
+ /* XXX: use WFI */
+ for (;;);
+}
+
+
+typedef void (*handler)(void);
+extern uint8_t __main_stack_end__;
+
+extern void svc (void);
+extern void preempt (void);
+extern void chx_timer_expired (void);
+
+handler vector_table[] __attribute__ ((section(".startup.vectors"))) = {
+ (handler)&__main_stack_end__,
+ entry,
+ nmi, /* nmi */
+ hard_fault, /* hard fault */
+ /* 0x10 */
+ mem_manage, /* mem manage */
+ bus_fault, /* bus fault */
+ usage_fault, /* usage fault */
+ none,
+ /* 0x20 */
+ none, none, none, /* reserved */
+ svc, /* SVCall */
+ none, /* Debug */
+ none, /* reserved */
+ preempt, /* PendSV */
+ chx_timer_expired, /* SysTick */
+ /* 0x40 */
+ none, none, none, none, none, none, none, none,
+ /* 0x60 */
+ none, none, none, none, none, none, none, none,
+ /* 0x80 */
+ none, none, none, none,
+ /* 0x90 */
+ none,
+};
diff --git a/example/Makefile b/example/Makefile
new file mode 100644
index 0000000..085d42b
--- /dev/null
+++ b/example/Makefile
@@ -0,0 +1,31 @@
+# Makefile for example application of Chopstx
+
+PROJECT = sample
+
+CHOPSTX = ..
+LDSCRIPT= sample.ld
+CSRC = sys.c aes-constant-ft.c sample.c
+
+###################################
+CROSS = arm-none-eabi-
+CC = $(CROSS)gcc
+LD = $(CROSS)gcc
+OBJCOPY = $(CROSS)objcopy
+
+MCU = cortex-m3
+CWARN = -Wall -Wextra -Wstrict-prototypes
+DEFS = -DFREE_STANDING
+OPT = -O3 -Os -g
+LIBS =
+
+####################
+include ../rules.mk
+
+board.h:
+ @echo Please make a symbolic link \'board.h\' to a file in ../board;
+ @exit 1
+
+sys.c: board.h
+
+distclean: clean
+ rm -f board.h
diff --git a/example/aes-constant-ft.c b/example/aes-constant-ft.c
new file mode 100644
index 0000000..21d1ba7
--- /dev/null
+++ b/example/aes-constant-ft.c
@@ -0,0 +1,145 @@
+/*
+ * aes-constant-ft.c - AES forward tables.
+ *
+ * We need something useful for the initial flash ROM page (4 Ki
+ * bytes), which cannot be modified after installation. Even after
+ * upgrade of the firmware, it stays intact.
+ *
+ * We decide to put 3/4 of AES forward tables to fill 3 Ki bytes, as
+ * its useful and it won't change.
+ *
+ * The code was taken from aes.c of PolarSSL version 0.14, and then,
+ * modified to add section names.
+ *
+ * Since this is just a data, it wouldn't be copyright-able, but the
+ * original auther would claim so. Thus, we put original copyright
+ * notice here. It is highly likely that there will be no such a
+ * thing for copyright. Nevertheless, we think that PolarSSL is good
+ * software to address here, and encourage people using it.
+ *
+ */
+
+#include <stdint.h>
+
+/*
+ * Original copyright notice is below:
+ */
+
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+ V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+ V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+ V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+ V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+ V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+ V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+ V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+ V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+ V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+ V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+ V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+ V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+ V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+ V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+ V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+ V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+ V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+ V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+ V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+ V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+ V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+ V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+ V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+ V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+ V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+ V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+ V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+ V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+ V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+ V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+ V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+ V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+ V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+ V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+ V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+ V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+ V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+ V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+ V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+ V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+ V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+ V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+ V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+ V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+ V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+ V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+ V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+ V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+ V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+ V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+ V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+ V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+ V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+ V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+ V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+ V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+ V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+ V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+ V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+ V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+ V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+ V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+ V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+ V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT };
+#undef V
+
+#ifdef ORIGINAL_IMPLEMENTATION
+#define V(a,b,c,d) 0x##d##a##b##c
+const uint32_t FT3[256] = { FT };
+#undef V
+#endif
diff --git a/example/sample.c b/example/sample.c
new file mode 100644
index 0000000..9441a57
--- /dev/null
+++ b/example/sample.c
@@ -0,0 +1,138 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <chopstx.h>
+#include "sys.h" /* for set_led */
+
+static chopstx_mutex_t mtx;
+static chopstx_cond_t cnd0;
+static chopstx_cond_t cnd1;
+static chopstx_cond_t cnd_intr;
+
+static uint8_t u, v;
+static uint8_t m; /* 0..100 */
+
+static void *
+pwm (void *arg)
+{
+ (void)arg;
+
+ chopstx_mutex_lock (&mtx);
+ chopstx_cond_wait (&cnd0, &mtx);
+ chopstx_mutex_unlock (&mtx);
+
+ while (1)
+ {
+ set_led (u&v);
+ chopstx_usleep (m);
+ set_led (0);
+ chopstx_usleep (100-m);
+ }
+
+ return NULL;
+}
+
+static void *
+blk (void *arg)
+{
+ (void)arg;
+
+ chopstx_mutex_lock (&mtx);
+ chopstx_cond_wait (&cnd1, &mtx);
+ chopstx_mutex_unlock (&mtx);
+
+ while (1)
+ {
+ v = 0;
+ chopstx_usleep (200*1000);
+ v = 1;
+ chopstx_usleep (200*1000);
+ }
+
+ return NULL;
+}
+
+#define INTR_REQ_0 0
+
+static void *
+intr (void *arg)
+{
+ (void)arg;
+ chopstix_intr_t interrupt;
+
+ chopstx_intr_register (&interrupt, INTR_REQ_0);
+
+ while (1)
+ {
+ chopstx_wait_intr (&interrupt);
+
+ /* process interrupt... */
+ chopstx_usleep (200*1000);
+ }
+
+ return NULL;
+}
+
+#define PRIO_PWM 3
+#define PRIO_BLK 2
+#define PRIO_INTR 2
+
+extern uint8_t __process1_stack_base__, __process1_stack_size__;
+extern uint8_t __process2_stack_base__, __process2_stack_size__;
+extern uint8_t __process3_stack_base__, __process3_stack_size__;
+
+const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
+const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
+
+const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
+const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
+
+const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
+const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
+
+
+int
+main (int argc, const char *argv[])
+{
+ chopstx_t thd;
+ chopstx_attr_t attr;
+
+ (void)argc;
+ (void)argv;
+
+ chopstx_mutex_init (&mtx);
+ chopstx_cond_init (&cnd0);
+ chopstx_cond_init (&cnd1);
+
+ m = 10;
+
+ chopstx_attr_init (&attr);
+ chopstx_attr_setschedparam (&attr, PRIO_PWM);
+ chopstx_attr_setstack (&attr, __stackaddr_pwm, __stacksize_pwm);
+
+ chopstx_create (&thd, &attr, pwm, NULL);
+
+ chopstx_attr_setschedparam (&attr, PRIO_BLK);
+ chopstx_attr_setstack (&attr, __stackaddr_blk, __stacksize_blk);
+
+ chopstx_create (&thd, &attr, blk, NULL);
+
+ chopstx_attr_setschedparam (&attr, PRIO_INTR);
+ chopstx_attr_setstack (&attr, __stackaddr_intr, __stacksize_intr);
+
+ chopstx_create (&thd, &attr, intr, NULL);
+
+ chopstx_usleep (200*1000);
+
+ chopstx_mutex_lock (&mtx);
+ chopstx_cond_signal (&cnd0);
+ chopstx_cond_signal (&cnd1);
+ chopstx_mutex_unlock (&mtx);
+
+ while (1)
+ {
+ u ^= 1;
+ chopstx_usleep (200*1000*6);
+ }
+
+ return 0;
+}
diff --git a/example/sample.ld b/example/sample.ld
new file mode 100644
index 0000000..f98d789
--- /dev/null
+++ b/example/sample.ld
@@ -0,0 +1,142 @@
+/*
+ * ST32F103 memory setup.
+ */
+__main_stack_size__ = 0x0100; /* Exception handlers */
+__process0_stack_size__ = 0x0100; /* Main program */
+__process1_stack_size__ = 0x0100; /* first thread program */
+__process2_stack_size__ = 0x0100; /* second thread program */
+__process3_stack_size__ = 0x0100; /* third thread program */
+
+MEMORY
+{
+ flash0 : org = 0x08000000, len = 4k
+ flash : org = 0x08000000+0x1000, len = 60k
+ ram : org = 0x20000000, len = 20k
+}
+
+__flash_start__ = 0x08001000;
+__flash_end__ = 0x08020000;
+
+__ram_start__ = ORIGIN(ram);
+__ram_size__ = 20k;
+__ram_end__ = __ram_start__ + __ram_size__;
+
+SECTIONS
+{
+ . = 0;
+
+ .sys : ALIGN(16) SUBALIGN(16)
+ {
+ _sys = .;
+ KEEP(*(.vectors))
+ . = ALIGN(16);
+ *(.sys.version)
+ build/sys.o(.text)
+ build/sys.o(.text.*)
+ build/sys.o(.rodata)
+ build/sys.o(.rodata.*)
+ . = ALIGN(1024);
+ *(.sys.0)
+ *(.sys.1)
+ *(.sys.2)
+ } > flash0
+
+ _text = .;
+
+ .startup : ALIGN(128) SUBALIGN(128)
+ {
+ KEEP(*(.startup.vectors))
+ . = ALIGN (16);
+ } > flash =0xffffffff
+
+ .text : ALIGN(16) SUBALIGN(16)
+ {
+ *(.text.startup.*)
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata.*)
+ *(.glue_7t)
+ *(.glue_7)
+ *(.gcc*)
+ } > flash
+
+ .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > flash
+
+ .ARM.exidx : {
+ PROVIDE(__exidx_start = .);
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ PROVIDE(__exidx_end = .);
+ } > flash
+
+ .eh_frame_hdr : {*(.eh_frame_hdr)} > flash
+
+ .eh_frame : ONLY_IF_RO {*(.eh_frame)} > flash
+
+ .textalign : ONLY_IF_RO { . = ALIGN(8); } > flash
+
+ _etext = .;
+ _textdata = _etext;
+
+ .process_stack :
+ {
+ . = ALIGN(8);
+ __process3_stack_base__ = .;
+ . += __process3_stack_size__;
+ . = ALIGN(8);
+ __process_stack3_end__ = .;
+ __process2_stack_base__ = .;
+ . += __process2_stack_size__;
+ . = ALIGN(8);
+ __process_stack2_end__ = .;
+ __process1_stack_base__ = .;
+ . += __process1_stack_size__;
+ . = ALIGN(8);
+ __process_stack1_end__ = .;
+ __process0_stack_base__ = .;
+ . += __process0_stack_size__;
+ . = ALIGN(8);
+ __process0_stack_end__ = .;
+ } > ram
+
+ .main_stack :
+ {
+ . = ALIGN(8);
+ __main_stack_base__ = .;
+ . += __main_stack_size__;
+ . = ALIGN(8);
+ __main_stack_end__ = .;
+ } > ram
+
+ .data :
+ {
+ . = ALIGN(4);
+ PROVIDE(_data = .);
+ *(.data)
+ . = ALIGN(4);
+ *(.data.*)
+ . = ALIGN(4);
+ *(.ramtext)
+ . = ALIGN(4);
+ PROVIDE(_edata = .);
+ } > ram AT > flash
+
+ .bss :
+ {
+ . = ALIGN(4);
+ PROVIDE(_bss_start = .);
+ *(.bss)
+ . = ALIGN(4);
+ *(.bss.*)
+ . = ALIGN(4);
+ *(COMMON)
+ . = ALIGN(4);
+ PROVIDE(_bss_end = .);
+ } > ram
+
+ PROVIDE(end = .);
+ _end = .;
+}
+
+__heap_base__ = _end;
+__heap_end__ = __ram_end__;
diff --git a/example/sys.c b/example/sys.c
new file mode 100644
index 0000000..1e6c030
--- /dev/null
+++ b/example/sys.c
@@ -0,0 +1,600 @@
+/*
+ * sys.c - system routines for the initial page for STM32F103.
+ *
+ * Copyright (C) 2013 Flying Stone Technology
+ * Author: NIIBE Yutaka <gniibe@fsij.org>
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ *
+ * When the flash ROM is protected, we cannot modify the initial page.
+ * We put some system routines (which is useful for any program) here.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "board.h"
+
+
+#define CORTEX_PRIORITY_BITS 4
+#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS))
+#define USB_LP_CAN1_RX0_IRQn 20
+#define STM32_USB_IRQ_PRIORITY 11
+
+#define FLASH_PAGE_SIZE 1024
+
+
+
+#define STM32_SW_PLL (2 << 0)
+#define STM32_PLLSRC_HSE (1 << 16)
+
+#define STM32_PLLXTPRE_DIV1 (0 << 17)
+#define STM32_PLLXTPRE_DIV2 (1 << 17)
+
+#define STM32_HPRE_DIV1 (0 << 4)
+
+#define STM32_PPRE1_DIV2 (4 << 8)
+
+#define STM32_PPRE2_DIV1 (0 << 11)
+#define STM32_PPRE2_DIV2 (4 << 11)
+
+#define STM32_ADCPRE_DIV4 (1 << 14)
+#define STM32_ADCPRE_DIV6 (2 << 14)
+
+#define STM32_USBPRE_DIV1P5 (0 << 22)
+
+#define STM32_MCO_NOCLOCK (0 << 24)
+
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV2
+#define STM32_PPRE2 STM32_PPRE2_DIV1
+#define STM32_ADCPRE STM32_ADCPRE_DIV6
+#define STM32_MCOSEL STM32_MCO_NOCLOCK
+#define STM32_USBPRE STM32_USBPRE_DIV1P5
+
+#define STM32_PLLCLKIN (STM32_HSECLK / 1)
+#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18)
+#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)
+#define STM32_SYSCLK STM32_PLLCLKOUT
+#define STM32_HCLK (STM32_SYSCLK / 1)
+
+#define STM32_FLASHBITS 0x00000012
+
+struct NVIC {
+ uint32_t ISER[8];
+ uint32_t unused1[24];
+ uint32_t ICER[8];
+ uint32_t unused2[24];
+ uint32_t ISPR[8];
+ uint32_t unused3[24];
+ uint32_t ICPR[8];
+ uint32_t unused4[24];
+ uint32_t IABR[8];
+ uint32_t unused5[56];
+ uint32_t IPR[60];
+};
+
+#define NVICBase ((struct NVIC *)0xE000E100)
+#define NVIC_ISER(n) (NVICBase->ISER[n])
+#define NVIC_ICPR(n) (NVICBase->ICPR[n])
+#define NVIC_IPR(n) (NVICBase->IPR[n])
+
+static void
+nvic_enable_vector (uint32_t n, uint32_t prio)
+{
+ unsigned int sh = (n & 3) << 3;
+
+ NVIC_IPR (n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh);
+ NVIC_ICPR (n >> 5) = 1 << (n & 0x1F);
+ NVIC_ISER (n >> 5) = 1 << (n & 0x1F);
+}
+
+
+#define PERIPH_BASE 0x40000000
+#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
+#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
+
+struct RCC {
+ volatile uint32_t CR;
+ volatile uint32_t CFGR;
+ volatile uint32_t CIR;
+ volatile uint32_t APB2RSTR;
+ volatile uint32_t APB1RSTR;
+ volatile uint32_t AHBENR;
+ volatile uint32_t APB2ENR;
+ volatile uint32_t APB1ENR;
+ volatile uint32_t BDCR;
+ volatile uint32_t CSR;
+};
+
+#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
+#define RCC ((struct RCC *)RCC_BASE)
+
+#define RCC_APB1ENR_USBEN 0x00800000
+#define RCC_APB1RSTR_USBRST 0x00800000
+
+#define RCC_CR_HSION 0x00000001
+#define RCC_CR_HSIRDY 0x00000002
+#define RCC_CR_HSITRIM 0x000000F8
+#define RCC_CR_HSEON 0x00010000
+#define RCC_CR_HSERDY 0x00020000
+#define RCC_CR_PLLON 0x01000000
+#define RCC_CR_PLLRDY 0x02000000
+
+#define RCC_CFGR_SWS 0x0000000C
+#define RCC_CFGR_SWS_HSI 0x00000000
+
+#define RCC_AHBENR_CRCEN 0x0040
+
+struct FLASH {
+ volatile uint32_t ACR;
+ volatile uint32_t KEYR;
+ volatile uint32_t OPTKEYR;
+ volatile uint32_t SR;
+ volatile uint32_t CR;
+ volatile uint32_t AR;
+ volatile uint32_t RESERVED;
+ volatile uint32_t OBR;
+ volatile uint32_t WRPR;
+};
+
+#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000)
+#define FLASH ((struct FLASH *) FLASH_R_BASE)
+
+static void
+clock_init (void)
+{
+ /* HSI setup */
+ RCC->CR |= RCC_CR_HSION;
+ while (!(RCC->CR & RCC_CR_HSIRDY))
+ ;
+ RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION;
+ RCC->CFGR = 0;
+ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
+ ;
+
+ /* HSE setup */
+ RCC->CR |= RCC_CR_HSEON;
+ while (!(RCC->CR & RCC_CR_HSERDY))
+ ;
+
+ /* PLL setup */
+ RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC;
+ RCC->CR |= RCC_CR_PLLON;
+ while (!(RCC->CR & RCC_CR_PLLRDY))
+ ;
+
+ /* Clock settings */
+ RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE
+ | STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
+
+ /* Flash setup */
+ FLASH->ACR = STM32_FLASHBITS;
+
+ /* CRC */
+ RCC->AHBENR |= RCC_AHBENR_CRCEN;
+
+ /* Switching on the configured clock source. */
+ RCC->CFGR |= STM32_SW;
+ while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
+ ;
+}
+
+#define RCC_APB2ENR_IOPAEN 0x00000004
+#define RCC_APB2RSTR_IOPARST 0x00000004
+#define RCC_APB2ENR_IOPBEN 0x00000008
+#define RCC_APB2RSTR_IOPBRST 0x00000008
+#define RCC_APB2ENR_IOPCEN 0x00000010
+#define RCC_APB2RSTR_IOPCRST 0x00000010
+#define RCC_APB2ENR_IOPDEN 0x00000020
+#define RCC_APB2RSTR_IOPDRST 0x00000020
+
+
+struct GPIO {
+ volatile uint32_t CRL;
+ volatile uint32_t CRH;
+ volatile uint32_t IDR;
+ volatile uint32_t ODR;
+ volatile uint32_t BSRR;
+ volatile uint32_t BRR;
+ volatile uint32_t LCKR;
+};
+
+#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
+#define GPIOA ((struct GPIO *) GPIOA_BASE)
+#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
+#define GPIOB ((struct GPIO *) GPIOB_BASE)
+#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
+#define GPIOC ((struct GPIO *) GPIOC_BASE)
+#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
+#define GPIOD ((struct GPIO *) GPIOD_BASE)
+#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
+#define GPIOE ((struct GPIO *) GPIOE_BASE)
+
+#define GPIO_USB ((struct GPIO *) GPIO_USB_BASE)
+#define GPIO_LED ((struct GPIO *) GPIO_LED_BASE)
+
+static void
+gpio_init (void)
+{
+ /* Enable GPIO clock. */
+ RCC->APB2ENR |= RCC_APB2ENR_IOP_EN;
+ RCC->APB2RSTR = RCC_APB2RSTR_IOP_RST;
+ RCC->APB2RSTR = 0;
+
+ GPIO_USB->ODR = VAL_GPIO_ODR;
+ GPIO_USB->CRH = VAL_GPIO_CRH;
+ GPIO_USB->CRL = VAL_GPIO_CRL;
+
+#if GPIO_USB_BASE != GPIO_LED_BASE
+ GPIO_LED->ODR = VAL_GPIO_LED_ODR;
+ GPIO_LED->CRH = VAL_GPIO_LED_CRH;
+ GPIO_LED->CRL = VAL_GPIO_LED_CRL;
+#endif
+}
+
+static void
+usb_cable_config (int enable)
+{
+#if defined(GPIO_USB_SET_TO_ENABLE)
+ if (enable)
+ GPIO_USB->BSRR = (1 << GPIO_USB_SET_TO_ENABLE);
+ else
+ GPIO_USB->BRR = (1 << GPIO_USB_SET_TO_ENABLE);
+#elif defined(GPIO_USB_CLEAR_TO_ENABLE)
+ if (enable)
+ GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE);
+ else
+ GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE);
+#else
+ (void)enable;
+#endif
+}
+
+void
+set_led (int on)
+{
+#if defined(GPIO_LED_CLEAR_TO_EMIT)
+ if (on)
+ GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT);
+ else
+ GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT);
+#else
+ if (on)
+ GPIO_LED->BSRR = (1 << GPIO_LED_SET_TO_EMIT);
+ else
+ GPIO_LED->BRR = (1 << GPIO_LED_SET_TO_EMIT);
+#endif
+}
+
+static void wait (int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ asm volatile ("" : : "r" (i) : "memory");
+}
+
+#define USB_IRQ 20
+#define USB_IRQ_PRIORITY ((11) << 4)
+
+static void
+usb_lld_sys_shutdown (void)
+{
+ RCC->APB1ENR &= ~RCC_APB1ENR_USBEN;
+ RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
+ usb_cable_config (0);
+}
+
+static void
+usb_lld_sys_init (void)
+{
+ if ((RCC->APB1ENR & RCC_APB1ENR_USBEN)
+ && (RCC->APB1RSTR & RCC_APB1RSTR_USBRST) == 0)
+ /* Make sure the device is disconnected, even after core reset. */
+ {
+ usb_lld_sys_shutdown ();
+ /* Disconnect requires SE0 (>= 2.5uS). */
+ wait (300);
+ }
+
+ usb_cable_config (1);
+ RCC->APB1ENR |= RCC_APB1ENR_USBEN;
+ nvic_enable_vector (USB_LP_CAN1_RX0_IRQn,
+ CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
+ /*
+ * Note that we also have other IRQ(s):
+ * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous)
+ * USBWakeUp_IRQn (suspend/resume)
+ */
+ RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
+ RCC->APB1RSTR = 0;
+}
+
+#define FLASH_KEY1 0x45670123UL
+#define FLASH_KEY2 0xCDEF89ABUL
+
+enum flash_status
+{
+ FLASH_BUSY = 1,
+ FLASH_ERROR_PG,
+ FLASH_ERROR_WRP,
+ FLASH_COMPLETE,
+ FLASH_TIMEOUT
+};
+
+static void __attribute__ ((used))
+flash_unlock (void)
+{
+ FLASH->KEYR = FLASH_KEY1;
+ FLASH->KEYR = FLASH_KEY2;
+}
+
+
+#define intr_disable() asm volatile ("cpsid i" : : : "memory")
+
+#define intr_enable() asm volatile ("msr BASEPRI, %0\n\t" \
+ "cpsie i" : : "r" (0) : "memory")
+
+#define FLASH_SR_BSY 0x01
+#define FLASH_SR_PGERR 0x04
+#define FLASH_SR_WRPRTERR 0x10
+#define FLASH_SR_EOP 0x20
+
+#define FLASH_CR_PG 0x0001
+#define FLASH_CR_PER 0x0002
+#define FLASH_CR_MER 0x0004
+#define FLASH_CR_OPTPG 0x0010
+#define FLASH_CR_OPTER 0x0020
+#define FLASH_CR_STRT 0x0040
+#define FLASH_CR_LOCK 0x0080
+#define FLASH_CR_OPTWRE 0x0200
+#define FLASH_CR_ERRIE 0x0400
+#define FLASH_CR_EOPIE 0x1000
+
+static int
+flash_wait_for_last_operation (uint32_t timeout)
+{
+ int status;
+
+ do
+ {
+ status = FLASH->SR;
+ if (--timeout == 0)
+ break;
+ }
+ while ((status & FLASH_SR_BSY) != 0);
+
+ return status & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR);
+}
+
+#define FLASH_PROGRAM_TIMEOUT 0x00010000
+#define FLASH_ERASE_TIMEOUT 0x01000000
+
+static int
+flash_program_halfword (uint32_t addr, uint16_t data)
+{
+ int status;
+
+ status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
+
+ intr_disable ();
+ if (status == 0)
+ {
+ FLASH->CR |= FLASH_CR_PG;
+
+ *(volatile uint16_t *)addr = data;
+
+ status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
+ FLASH->CR &= ~FLASH_CR_PG;
+ }
+ intr_enable ();
+
+ return status;
+}
+
+static int
+flash_erase_page (uint32_t addr)
+{
+ int status;
+
+ status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
+
+ intr_disable ();
+ if (status == 0)
+ {
+ FLASH->CR |= FLASH_CR_PER;
+ FLASH->AR = addr;
+ FLASH->CR |= FLASH_CR_STRT;
+
+ status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
+ FLASH->CR &= ~FLASH_CR_PER;
+ }
+ intr_enable ();
+
+ return status;
+}
+
+static int
+flash_check_blank (const uint8_t *p_start, size_t size)
+{
+ const uint8_t *p;
+
+ for (p = p_start; p < p_start + size; p++)
+ if (*p != 0xff)
+ return 0;
+
+ return 1;
+}
+
+extern uint8_t __flash_start__, __flash_end__;
+
+static int
+flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
+{
+ int status;
+ uint32_t flash_start = (uint32_t)&__flash_start__;
+ uint32_t flash_end = (uint32_t)&__flash_end__;
+
+ if (dst_addr < flash_start || dst_addr + len > flash_end)
+ return 0;
+
+ while (len)
+ {
+ uint16_t hw = *src++;
+
+ hw |= (*src++ << 8);
+ status = flash_program_halfword (dst_addr, hw);
+ if (status != 0)
+ return 0; /* error return */
+
+ dst_addr += 2;
+ len -= 2;
+ }
+
+ return 1;
+}
+
+#define OPTION_BYTES_ADDR 0x1ffff800
+
+static int
+flash_protect (void)
+{
+ int status;
+ uint32_t option_bytes_value;
+
+ status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
+
+ intr_disable ();
+ if (status == 0)
+ {
+ FLASH->OPTKEYR = FLASH_KEY1;
+ FLASH->OPTKEYR = FLASH_KEY2;
+
+ FLASH->CR |= FLASH_CR_OPTER;
+ FLASH->CR |= FLASH_CR_STRT;
+
+ status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
+ FLASH->CR &= ~FLASH_CR_OPTER;
+ }
+ intr_enable ();
+
+ if (status != 0)
+ return 0;
+
+ option_bytes_value = *(uint32_t *)OPTION_BYTES_ADDR;
+ return (option_bytes_value & 0xff) == 0xff ? 1 : 0;
+}
+
+static void __attribute__((naked))
+flash_erase_all_and_exec (void (*entry)(void))
+{
+ uint32_t addr = (uint32_t)&__flash_start__;
+ uint32_t end = (uint32_t)&__flash_end__;
+ int r;
+
+ while (addr < end)
+ {
+ r = flash_erase_page (addr);
+ if (r != 0)
+ break;
+
+ addr += FLASH_PAGE_SIZE;
+ }
+
+ if (addr >= end)
+ (*entry) ();
+
+ for (;;);
+}
+
+struct SCB
+{
+ volatile uint32_t CPUID;
+ volatile uint32_t ICSR;
+ volatile uint32_t VTOR;
+ volatile uint32_t AIRCR;
+ volatile uint32_t SCR;
+ volatile uint32_t CCR;
+ volatile uint8_t SHP[12];
+ volatile uint32_t SHCSR;
+ volatile uint32_t CFSR;
+ volatile uint32_t HFSR;
+ volatile uint32_t DFSR;
+ volatile uint32_t MMFAR;
+ volatile uint32_t BFAR;
+ volatile uint32_t AFSR;
+ volatile uint32_t PFR[2];
+ volatile uint32_t DFR;
+ volatile uint32_t ADR;
+ volatile uint32_t MMFR[4];
+ volatile uint32_t ISAR[5];
+};
+
+#define SCS_BASE (0xE000E000)
+#define SCB_BASE (SCS_BASE + 0x0D00)
+#define SCB ((struct SCB *) SCB_BASE)
+
+#define SYSRESETREQ 0x04
+static void
+nvic_system_reset (void)
+{
+ SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ);
+ asm volatile ("dsb");
+}
+
+static void __attribute__ ((naked))
+reset (void)
+{
+ asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
+ "mov.w r0, #0xed00\n\t" /* r0 = SCR */
+ "movt r0, #0xe000\n\t"
+ "mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
+ "mov r2, #0x1000\n\t"
+ "add r1, r1, r2\n\t"
+ "sub r2, r2, #1\n\t"
+ "bic r1, r1, r2\n\t"
+ "str r1, [r0, #8]\n\t" /* Set SCR->VCR */
+ "ldr r0, [r1], #4\n\t"
+ "msr MSP, r0\n\t" /* Main (exception handler) stack. */
+ "ldr r0, [r1]\n\t" /* Reset handler. */
+ "bx r0\n"
+ : /* no output */ : /* no input */ : "memory");
+}
+
+typedef void (*handler)(void);
+extern uint8_t __ram_end__;
+
+extern const unsigned long *FT0, *FT1, *FT2;
+
+handler vector[] __attribute__ ((section(".vectors"))) = {
+ (handler)&__ram_end__,
+ reset,
+ (handler)set_led,
+ flash_unlock,
+ (handler)flash_program_halfword,
+ (handler)flash_erase_page,
+ (handler)flash_check_blank,
+ (handler)flash_write,
+ (handler)flash_protect,
+ (handler)flash_erase_all_and_exec,
+ usb_lld_sys_init,
+ usb_lld_sys_shutdown,
+ nvic_system_reset,
+ clock_init,
+ gpio_init,
+ (handler)&FT0,
+ (handler)&FT1,
+ (handler)&FT2,
+};
+
+const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
+ 3*2+2, /* bLength */
+ 0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE*/
+ /* sys version: "2.0" */
+ '2', 0, '.', 0, '0', 0,
+};
diff --git a/example/sys.h b/example/sys.h
new file mode 100644
index 0000000..bb1ea71
--- /dev/null
+++ b/example/sys.h
@@ -0,0 +1,97 @@
+extern const uint8_t sys_version[8];
+
+typedef void (*handler)(void);
+extern handler vector[18];
+
+static inline const uint8_t *
+unique_device_id (void)
+{
+ /* STM32F103 has 96-bit unique device identifier */
+ const uint8_t *addr = (const uint8_t *)0x1ffff7e8;
+
+ return addr;
+}
+
+static inline void
+set_led (int on)
+{
+ void (*func) (int) = (void (*)(int))vector[2];
+
+ return (*func) (on);
+}
+
+#if 0
+static inline void
+flash_unlock (void)
+{
+ (*vector[3]) ();
+}
+#endif
+
+static inline int
+flash_program_halfword (uint32_t addr, uint16_t data)
+{
+ int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[4];
+
+ return (*func) (addr, data);
+}
+
+static inline int
+flash_erase_page (uint32_t addr)
+{
+ int (*func) (uint32_t) = (int (*)(uint32_t))vector[5];
+
+ return (*func) (addr);
+}
+
+static inline int
+flash_check_blank (const uint8_t *p_start, size_t size)
+{
+ int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[6];
+
+ return (*func) (p_start, size);
+}
+
+static inline int
+flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
+{
+ int (*func) (uint32_t, const uint8_t *, size_t)
+ = (int (*)(uint32_t, const uint8_t *, size_t))vector[7];
+
+ return (*func) (dst_addr, src, len);
+}
+
+static inline int
+flash_protect (void)
+{
+ int (*func) (void) = (int (*)(void))vector[8];
+
+ return (*func) ();
+}
+
+static inline void __attribute__((noreturn))
+flash_erase_all_and_exec (void (*entry)(void))
+{
+ void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[9];
+
+ (*func) (entry);
+ for (;;);
+}
+
+static inline void
+usb_lld_sys_init (void)
+{
+ (*vector[10]) ();
+}
+
+static inline void
+usb_lld_sys_shutdown (void)
+{
+ (*vector[11]) ();
+}
+
+static inline void
+nvic_system_reset (void)
+{
+ (*vector[12]) ();
+}
diff --git a/rules.mk b/rules.mk
new file mode 100644
index 0000000..91c77ca
--- /dev/null
+++ b/rules.mk
@@ -0,0 +1,51 @@
+# Chopstx make rules.
+
+CSRC += $(CHOPSTX)/entry.c $(CHOPSTX)/chopstx.c
+INCDIR = $(CHOPSTX)
+
+BUILDDIR = build
+OUTFILES = $(BUILDDIR)/$(PROJECT).elf $(BUILDDIR)/$(PROJECT).bin
+
+OPT += -ffunction-sections -fdata-sections -fno-common
+
+OBJS = $(addprefix $(BUILDDIR)/, $(notdir $(CSRC:.c=.o)))
+
+IINCDIR = $(patsubst %,-I%,$(INCDIR))
+LLIBDIR = $(patsubst %,-L%,$(LIBDIR))
+
+VPATH = $(sort $(dir $(CSRC)))
+###
+MCFLAGS = -mcpu=$(MCU)
+
+CFLAGS = $(MCFLAGS) $(OPT) $(CWARN) -Wa,-alms=$(BUILDDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
+
+LDFLAGS = $(MCFLAGS) -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--gc-sections $(LLIBDIR)
+
+CFLAGS += -mthumb -mno-thumb-interwork -DTHUMB
+LDFLAGS += -mthumb -mno-thumb-interwork
+
+CFLAGS += -MD -MP -MF .dep/$(@F).d
+
+all: $(OBJS) $(OUTFILES)
+
+$(OBJS): | $(BUILDDIR)
+
+$(BUILDDIR):
+ mkdir -p $(BUILDDIR)
+
+$(OBJS) : $(BUILDDIR)/%.o : %.c Makefile
+ @echo
+ $(CC) -c $(CFLAGS) -I. $(IINCDIR) $< -o $@
+
+%.elf: $(OBJS) $(LDSCRIPT)
+ @echo
+ $(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
+
+%.bin: %.elf $(LDSCRIPT)
+ $(OBJCOPY) -O binary $< $@
+
+clean:
+ -rm -f -r .dep $(BUILDDIR)
+
+# Include dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)