diff --git a/hardware/MySensors/avr/boards.txt b/hardware/MySensors/avr/boards.txt
index a603989..7220cad 100644
--- a/hardware/MySensors/avr/boards.txt
+++ b/hardware/MySensors/avr/boards.txt
@@ -13,7 +13,7 @@ MysensorsMicro.bootloader.lock_bits=0x0F
MysensorsMicro.bootloader.low_fuses=0xE2
MysensorsMicro.bootloader.high_fuses=0xD2
MysensorsMicro.bootloader.extended_fuses=0xFE
-MysensorsMicro.bootloader.file=DualOptiboot/optiboot_atmega328p-pro8.hex
+MysensorsMicro.bootloader.file=DualOptiboot/optiboot_atmega328_pro_8MHz.hex
MysensorsMicro.build.board=AVR_MICRO8
MysensorsMicro.build.core=arduino:arduino
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/License.txt b/hardware/MySensors/avr/bootloaders/DualOptiboot/License.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/License.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/Makefile b/hardware/MySensors/avr/bootloaders/DualOptiboot/Makefile
new file mode 100644
index 0000000..95c806b
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/Makefile
@@ -0,0 +1,649 @@
+# Makefile for ATmegaBOOT
+# E.Lins, 18.7.2005
+# $Id$
+#
+# Instructions
+#
+# To make bootloader .hex file:
+# make diecimila
+# make lilypad
+# make ng
+# etc...
+#
+# To burn bootloader .hex file:
+# make diecimila_isp
+# make lilypad_isp
+# make ng_isp
+# etc...
+#
+# Edit History
+# 201303xx: WestfW: Major Makefile restructuring.
+# Allows options on Make command line "make xx LED=B3"
+# (see also pin_defs.h)
+# Divide into "chip" targets and "board" targets.
+# Most boards are (recursive) board targets with options.
+# Move isp target to separate makefile (fixes m8 EFUSE)
+# Some (many) targets will now be rebuilt when not
+# strictly necessary, so that options will be included.
+# (any "make" with options will always compile.)
+# Set many variables with ?= so they can be overridden
+# Use arduinoISP settings as default for ISP targets
+#
+
+#----------------------------------------------------------------------
+#
+# program name should not be changed...
+PROGRAM = optiboot
+
+# The default behavior is to build using tools that are in the users
+# current path variables, but we can also build using an installed
+# Arduino user IDE setup, or the Arduino source tree.
+# Uncomment this next lines to build within the arduino environment,
+# using the arduino-included avrgcc toolset (mac and pc)
+# ENV ?= arduino
+# ENV ?= arduinodev
+# OS ?= macosx
+# OS ?= windows
+
+# export symbols to recursive makes (for ISP)
+export
+
+# defaults
+MCU_TARGET = atmega168
+LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
+
+# Build environments
+# Start of some ugly makefile-isms to allow optiboot to be built
+# in several different environments. See the README.TXT file for
+# details.
+
+# default
+fixpath = $(1)
+
+ifeq ($(ENV), arduino)
+# For Arduino, we assume that we're connected to the optiboot directory
+# included with the arduino distribution, which means that the full set
+# of avr-tools are "right up there" in standard places.
+TOOLROOT = ../../../tools
+GCCROOT = $(TOOLROOT)/avr/bin/
+
+ifeq ($(OS), windows)
+# On windows, SOME of the tool paths will need to have backslashes instead
+# of forward slashes (because they use windows cmd.exe for execution instead
+# of a unix/mingw shell?) We also have to ensure that a consistent shell
+# is used even if a unix shell is installed (ie as part of WINAVR)
+fixpath = $(subst /,\,$1)
+SHELL = cmd.exe
+endif
+
+else ifeq ($(ENV), arduinodev)
+# Arduino IDE source code environment. Use the unpacked compilers created
+# by the build (you'll need to do "ant build" first.)
+ifeq ($(OS), macosx)
+TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
+endif
+ifeq ($(OS), windows)
+TOOLROOT = ../../../../build/windows/work/hardware/tools
+endif
+
+GCCROOT = $(TOOLROOT)/avr/bin/
+AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
+
+else
+GCCROOT =
+AVRDUDE_CONF =
+endif
+
+STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
+STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
+ -lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
+STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
+#
+# End of build environment code.
+
+
+OBJ = $(PROGRAM).o
+OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mrelax
+
+DEFS =
+LIBS =
+
+CC = $(GCCROOT)avr-gcc
+
+# Override is only needed by avr-lib build system.
+
+override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
+override LDFLAGS = $(LDSECTIONS) -Wl,--relax -nostartfiles -nostdlib
+#-Wl,--gc-sections
+
+OBJCOPY = $(GCCROOT)avr-objcopy
+OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump)
+
+SIZE = $(GCCROOT)avr-size
+
+#
+# Make command-line Options.
+# Permit commands like "make atmega328 LED_START_FLASHES=10" to pass the
+# appropriate parameters ("-DLED_START_FLASHES=10") to gcc
+#
+
+ifdef BAUD_RATE
+BAUD_RATE_CMD = -DBAUD_RATE=$(BAUD_RATE)
+dummy = FORCE
+else
+BAUD_RATE_CMD = -DBAUD_RATE=115200
+endif
+
+ifdef LED_START_FLASHES
+LED_START_FLASHES_CMD = -DLED_START_FLASHES=$(LED_START_FLASHES)
+dummy = FORCE
+else
+LED_START_FLASHES_CMD = -DLED_START_FLASHES=3
+endif
+
+# BIG_BOOT: Include extra features, up to 1K.
+ifdef BIGBOOT
+BIGBOOT_CMD = -DBIGBOOT=1
+dummy = FORCE
+endif
+
+ifdef SOFT_UART
+SOFT_UART_CMD = -DSOFT_UART=1
+dummy = FORCE
+endif
+
+ifdef LED_DATA_FLASH
+LED_DATA_FLASH_CMD = -DLED_DATA_FLASH=1
+dummy = FORCE
+endif
+
+ifdef LED
+LED_CMD = -DLED=$(LED)
+dummy = FORCE
+endif
+
+ifdef SINGLESPEED
+SSCMD = -DSINGLESPEED=1
+endif
+
+COMMON_OPTIONS = $(BAUD_RATE_CMD) $(LED_START_FLASHES_CMD) $(BIGBOOT_CMD)
+COMMON_OPTIONS += $(SOFT_UART_CMD) $(LED_DATA_FLASH_CMD) $(LED_CMD) $(SSCMD)
+
+#UART is handled separately and only passed for devices with more than one.
+ifdef UART
+UARTCMD = -DUART=$(UART)
+endif
+
+# Not supported yet
+# ifdef SUPPORT_EEPROM
+# SUPPORT_EEPROM_CMD = -DSUPPORT_EEPROM
+# dummy = FORCE
+# endif
+
+# Not supported yet
+# ifdef TIMEOUT_MS
+# TIMEOUT_MS_CMD = -DTIMEOUT_MS=$(TIMEOUT_MS)
+# dummy = FORCE
+# endif
+#
+
+#---------------------------------------------------------------------------
+# "Chip-level Platform" targets.
+# A "Chip-level Platform" compiles for a particular chip, but probably does
+# not have "standard" values for things like clock speed, LED pin, etc.
+# Makes for chip-level platforms should usually explicitly define their
+# options like: "make atmega1285 AVR_FREQ=16000000L LED=D0"
+#---------------------------------------------------------------------------
+#
+# Note about fuses:
+# the efuse should really be 0xf8; since, however, only the lower
+# three bits of that byte are used on the atmega168, avrdude gets
+# confused if you specify 1's for the higher bits, see:
+# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
+#
+# similarly, the lock bits should be 0xff instead of 0x3f (to
+# unlock the bootloader section) and 0xcf instead of 0x2f (to
+# lock it), but since the high two bits of the lock byte are
+# unused, avrdude would get confused.
+#---------------------------------------------------------------------------
+#
+
+# Test platforms
+# Virtual boot block test
+virboot328: TARGET = atmega328
+virboot328: MCU_TARGET = atmega328p
+virboot328: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT'
+virboot328: AVR_FREQ ?= 16000000L
+virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
+virboot328: $(PROGRAM)_atmega328.hex
+virboot328: $(PROGRAM)_atmega328.lst
+
+# Diecimila, Duemilanove with m168, and NG use identical bootloaders
+# Call it "atmega168" for generality and clarity, keep "diecimila" for
+# backward compatibility of makefile
+#
+atmega168: TARGET = atmega168
+atmega168: MCU_TARGET = atmega168
+atmega168: CFLAGS += $(COMMON_OPTIONS)
+atmega168: AVR_FREQ ?= 16000000L
+atmega168: $(PROGRAM)_atmega168.hex
+atmega168: $(PROGRAM)_atmega168.lst
+
+atmega168_isp: atmega168
+atmega168_isp: TARGET = atmega168
+# 2.7V brownout
+atmega168_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega168_isp: LFUSE ?= FF
+# 512 byte boot
+atmega168_isp: EFUSE ?= 04
+atmega168_isp: isp
+
+atmega328: TARGET = atmega328
+atmega328: MCU_TARGET = atmega328p
+atmega328: CFLAGS += $(COMMON_OPTIONS)
+atmega328: AVR_FREQ ?= 16000000L
+atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7c00 -Wl,--section-start=.version=0x7ffe
+atmega328: $(PROGRAM)_atmega328.hex
+atmega328: $(PROGRAM)_atmega328.lst
+
+atmega328_isp: atmega328
+atmega328_isp: TARGET = atmega328
+atmega328_isp: MCU_TARGET = atmega328p
+# 512 byte boot, SPIEN
+atmega328_isp: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega328_isp: LFUSE ?= FF
+# 2.7V brownout
+atmega328_isp: EFUSE ?= FD
+atmega328_isp: isp
+
+atmega644p: TARGET = atmega644p
+atmega644p: MCU_TARGET = atmega644p
+atmega644p: CFLAGS += $(COMMON_OPTIONS) -DBIGBOOT $(LED_CMD)
+atmega644p: AVR_FREQ ?= 16000000L
+atmega644p: LDSECTIONS = -Wl,--section-start=.text=0xfc00 -Wl,--section-start=.version=0xfffe
+atmega644p: CFLAGS += $(UARTCMD)
+atmega644p: $(PROGRAM)_atmega644p.hex
+atmega644p: $(PROGRAM)_atmega644p.lst
+
+atmega1284: TARGET = atmega1284p
+atmega1284: MCU_TARGET = atmega1284p
+atmega1284: CFLAGS += $(COMMON_OPTIONS) -DBIGBOOT $(LED_CMD)
+atmega1284: AVR_FREQ ?= 16000000L
+atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
+atmega1284: CFLAGS += $(UARTCMD)
+atmega1284: $(PROGRAM)_atmega1284p.hex
+atmega1284: $(PROGRAM)_atmega1284p.lst
+
+atmega1284p: atmega1284
+
+atmega1284_isp: atmega1284
+atmega1284_isp: TARGET = atmega1284p
+atmega1284_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+atmega1284_isp: HFUSE ?= DE
+# Full Swing xtal (16MHz) 16KCK/14CK+65ms
+atmega1284_isp: LFUSE ?= F7
+# 2.7V brownout
+atmega1284_isp: EFUSE ?= FD
+atmega1284_isp: isp
+
+#Atmega1280
+atmega1280: MCU_TARGET = atmega1280
+atmega1280: CFLAGS += $(COMMON_OPTIONS) -DBIGBOOT $(UART_CMD)
+atmega1280: AVR_FREQ ?= 16000000L
+atmega1280: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
+atmega1280: $(PROGRAM)_atmega1280.hex
+atmega1280: $(PROGRAM)_atmega1280.lst
+
+
+# ATmega8
+#
+atmega8: TARGET = atmega8
+atmega8: MCU_TARGET = atmega8
+atmega8: CFLAGS += $(COMMON_OPTIONS)
+atmega8: AVR_FREQ ?= 16000000L
+atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
+atmega8: $(PROGRAM)_atmega8.hex
+atmega8: $(PROGRAM)_atmega8.lst
+
+atmega8_isp: atmega8
+atmega8_isp: TARGET = atmega8
+atmega8_isp: MCU_TARGET = atmega8
+# SPIEN, CKOPT (for full swing xtal), Bootsize=512B
+atmega8_isp: HFUSE ?= CC
+# 2.7V brownout, 16MHz Xtal, 16KCK/14CK+65ms
+atmega8_isp: LFUSE ?= BF
+atmega8_isp: isp
+
+# ATmega88
+#
+atmega88: TARGET = atmega88
+atmega88: MCU_TARGET = atmega88
+atmega88: CFLAGS += $(COMMON_OPTIONS)
+atmega88: AVR_FREQ ?= 16000000L
+atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
+atmega88: $(PROGRAM)_atmega88.hex
+atmega88: $(PROGRAM)_atmega88.lst
+
+atmega88_isp: atmega88
+atmega88_isp: TARGET = atmega88
+atmega88_isp: MCU_TARGET = atmega88
+# 2.7V brownout
+atmega88_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atemga88_isp: LFUSE ?= FF
+# 512 byte boot
+atmega88_isp: EFUSE ?= 04
+atmega88_isp: isp
+
+atmega32: TARGET = atmega32
+atmega32: MCU_TARGET = atmega32
+atmega32: CFLAGS += $(COMMON_OPTIONS)
+atmega32: AVR_FREQ ?= 11059200L
+atmega32: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
+atmega32: $(PROGRAM)_atmega32.hex
+atmega32: $(PROGRAM)_atmega32.lst
+
+atmega32_isp: atmega32
+atmega32_isp: TARGET = atmega32
+atmega32_isp: MCU_TARGET = atmega32
+# No OCD or JTAG, SPIEN, CKOPT (for full swing xtal), Bootsize=512B
+atmega32_isp: HFUSE ?= CE
+# 2.7V brownout, 16MHz Xtal, 16KCK/14CK+65ms
+atemga32_isp: LFUSE ?= BF
+atmega32_isp: isp
+
+
+
+#---------------------------------------------------------------------------
+# "Board-level Platform" targets.
+# A "Board-level Platform" implies a manufactured platform with a particular
+# AVR_FREQ, LED, and so on. Parameters are not particularly changable from
+# the "make" command line.
+# Most of the board-level platform builds should envoke make recursively
+# appropriate specific options
+#---------------------------------------------------------------------------
+# 20MHz clocked platforms
+#
+# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
+#
+
+pro20: TARGET = pro_20mhz
+pro20: CHIP = atmega168
+pro20:
+ $(MAKE) atmega168 AVR_FREQ=20000000L LED_START_FLASHES=3
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+pro20_isp: pro20
+pro20_isp: TARGET = pro_20mhz
+# 2.7V brownout
+pro20_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+pro20_isp: LFUSE ?= C6
+# 512 byte boot
+pro20_isp: EFUSE ?= 04
+pro20_isp: isp
+
+# 16MHz clocked platforms
+#
+# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
+#
+
+pro16: TARGET = pro_16MHz
+pro16: CHIP = atmega168
+pro16:
+ $(MAKE) $(CHIP) AVR_FREQ=16000000L LED_START_FLASHES=3
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+pro16_isp: pro16
+pro16_isp: TARGET = pro_16MHz
+# 2.7V brownout
+pro16_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+pro16_isp: LFUSE ?= C6
+# 512 byte boot
+pro16_isp: EFUSE ?= 04
+pro16_isp: isp
+
+diecimila: TARGET = diecimila
+diecimila: CHIP = atmega168
+diecimila:
+ $(MAKE) $(CHIP) AVR_FREQ=16000000L LED_START_FLASHES=3
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+diecimila_isp: diecimila
+diecimila_isp: TARGET = diecimila
+# 2.7V brownout
+diecimila_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+diecimila_isp: LFUSE ?= FF
+# 512 byte boot
+diecimila_isp: EFUSE ?= 04
+diecimila_isp: isp
+
+# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
+#
+sanguino: TARGET = $@
+sanguino: CHIP = atmega644p
+sanguino:
+ $(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B0
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+sanguino_isp: sanguino
+sanguino_isp: TARGET = sanguino
+sanguino_isp: MCU_TARGET = atmega644p
+# 1024 byte boot
+sanguino_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+sanguino_isp: LFUSE ?= F7
+# 2.7V brownout
+sanguino_isp: EFUSE ?= FD
+sanguino_isp: isp
+
+mighty1284: TARGET = $@
+mighty1284: CHIP = atmega1284p
+mighty1284:
+ $(MAKE) $(CHIP) AVR_FREQ=16000000L LED=D7
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+mighty1284_isp: mighty1284
+mighty1284_isp: TARGET = mighty1284
+mighty1284_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+mighty1284_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+mighty1284_isp: LFUSE ?= F7
+# 2.7V brownout
+mighty1284_isp: EFUSE ?= FD
+mighty1284_isp: isp
+
+bobuino: TARGET = $@
+bobuino: CHIP = atmega1284p
+bobuino:
+ $(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B5
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+bobuino_isp: bobuino
+bobuino_isp: TARGET = bobuino
+bobuino_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+bobuino_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+bobuino_isp: LFUSE ?= F7
+# 2.7V brownout
+bobuino_isp: EFUSE ?= FD
+bobuino_isp: isp
+
+# MEGA1280 Board (this is different from the atmega1280 chip platform)
+# Mega has a minimum boot size of 1024 bytes, so enable extra functions
+# Note that optiboot does not (can not) work on the MEGA2560
+#mega: TARGET = atmega1280
+mega1280: atmega1280
+
+
+mega1280_isp: mega1280
+mega1280_isp: TARGET = atmega1280
+mega1280_isp: MCU_TARGET = atmega1280
+# 1024 byte boot
+mega1280_isp: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+mega1280_isp: LFUSE ?= FF
+# 2.7V brownout; wants F5 for some reason...
+mega1280_isp: EFUSE ?= F5
+mega1280_isp: isp
+
+# 8MHz clocked platforms
+#
+# These are capable of 115200 baud
+# Note that "new" Arduinos with an AVR as USB/Serial converter will NOT work
+# with an 8MHz target Arduino. The bitrate errors are in opposite directions,
+# and total too large a number.
+#
+
+lilypad: TARGET = $@
+lilypad: CHIP = atmega168
+lilypad:
+ $(MAKE) $(CHIP) AVR_FREQ=8000000L LED_START_FLASHES=3
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+lilypad_isp: lilypad
+lilypad_isp: TARGET = lilypad
+# 2.7V brownout
+lilypad_isp: HFUSE ?= DD
+# Internal 8MHz osc (8MHz) Slow rising power
+lilypad_isp: LFUSE ?= E2
+# 512 byte boot
+lilypad_isp: EFUSE ?= 04
+lilypad_isp: isp
+
+# lilypad_resonator is the same as a 8MHz lilypad, except for fuses.
+lilypad_resonator: lilypad
+
+lilypad_resonator_isp: lilypad
+lilypad_resonator_isp: TARGET = lilypad
+# 2.7V brownout
+lilypad_resonator_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+lilypad_resonator_isp: LFUSE ?= C6
+# 512 byte boot
+lilypad_resonator_isp: EFUSE ?= 04
+lilypad_resonator_isp: isp
+
+pro8: TARGET = pro_8MHz
+pro8: CHIP = atmega328
+pro8:
+ $(MAKE) $(CHIP) AVR_FREQ=8000000L LED_START_FLASHES=3
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+pro8_isp: pro8
+pro8_isp: TARGET = pro_8MHz
+# 2.7V brownout
+pro8_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+pro8_isp: LFUSE ?= C6
+# 512 byte boot
+pro8_isp: EFUSE ?= 04
+pro8_isp: isp
+
+atmega328_pro8: TARGET = atmega328_pro_8MHz
+atmega328_pro8: CHIP = atmega328
+atmega328_pro8:
+ $(MAKE) $(CHIP) AVR_FREQ=8000000L LED_START_FLASHES=3
+ mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+ mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+atmega328_pro8_isp: atmega328_pro8
+atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
+atmega328_pro8_isp: MCU_TARGET = atmega328p
+# 512 byte boot, SPIEN
+atmega328_pro8_isp: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega328_pro8_isp: LFUSE ?= FF
+# 2.7V brownout
+atmega328_pro8_isp: EFUSE ?= DE
+atmega328_pro8_isp: isp
+
+mysensor_micro: atmega328_pro8
+mysensor_micro: target = atmega_pro_8MHz
+mysensor_micro: MCU_TARGET = atmega328p
+# 512 byte boot, SPIEN
+mysensor_micro: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+mysensor_micro: LFUSE ?= FF
+# 2.7V brownout
+mysensor_micro: EFUSE ?= DE
+mysensor_micro: LED=C3
+mysensor_micro: BAUD_RATE=57600
+
+# 1MHz clocked platforms
+#
+# These are capable of 9600 baud
+#
+
+luminet: TARGET = luminet
+luminet: MCU_TARGET = attiny84
+luminet: CFLAGS += $(COMMON_OPTIONS) '-DSOFT_UART' '-DBAUD_RATE=9600'
+luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
+luminet: AVR_FREQ ?= 1000000L
+luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
+luminet: $(PROGRAM)_luminet.hex
+luminet: $(PROGRAM)_luminet.lst
+
+luminet_isp: luminet
+luminet_isp: TARGET = luminet
+luminet_isp: MCU_TARGET = attiny84
+# Brownout disabled
+luminet_isp: HFUSE ?= DF
+# 1MHz internal oscillator, slowly rising power
+luminet_isp: LFUSE ?= 62
+# Self-programming enable
+luminet_isp: EFUSE ?= FE
+luminet_isp: isp
+
+
+#---------------------------------------------------------------------------
+#
+# Generic build instructions
+#
+
+FORCE:
+
+baudcheck: FORCE
+ - @$(CC) $(CFLAGS) -E baudcheck.c -o baudcheck.tmp.sh
+ - @sh baudcheck.tmp.sh
+
+isp: $(TARGET)
+ $(MAKE) -f Makefile.isp isp TARGET=$(TARGET)
+
+isp-stk500: $(PROGRAM)_$(TARGET).hex
+ $(STK500-1)
+ $(STK500-2)
+
+%.elf: $(OBJ) $(dummy)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
+ $(SIZE) $@
+
+clean:
+ rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.tmp.sh
+
+%.lst: %.elf
+ $(OBJDUMP) -h -S $< > $@
+
+%.hex: %.elf
+ $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
+
+%.srec: %.elf
+ $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
+
+%.bin: %.elf
+ $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/README.md b/hardware/MySensors/avr/bootloaders/DualOptiboot/README.md
new file mode 100644
index 0000000..06bb760
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/README.md
@@ -0,0 +1,40 @@
+DualOptiboot
+============
+
+Custom Optiboot to add wireless programming capability to Moteino
+Copyright Felix Rusu (2013-2014), felix@lowpowerlab.com
+More at: http://lowpowerlab.com/Moteino
+
+This Optiboot version is modified to add the capability of reflashing
+from an external SPI flash memory chip. As configured this will work
+with Moteino (www.lowpowerlab.com/Moteino) provided a SPI flash chip
+is present on the dedicated onboard footprint.
+Summary of how this Optiboot version works:
+- it looks for an external flash chip
+- if one is found (SPI returns valid data) it will further look
+ for a new sketch flash image signature and size
+ starting at address 0: FLXIMG:9999:XXXXXXXXXXX
+ where: - 'FLXIMG' is fixed signature indicating FLASH chip
+ contains a valid new flash image to be burned
+ - '9999' are 4 size bytes indicating how long the
+ new flash image is (how many bytes to read)
+ - 'XXXXXX' are the de-hexified bytes of the flash
+ pages to be burned
+ - ':' colons have fixed positions (delimiters)
+- if no valid signature/size are found, it will skip and
+ function as it normally would (listen to STK500 protocol on serial port)
+
+The added code will result in a compiled size of just under 1kb
+(Originally Optiboot takes just under 0.5kb)
+
+-------------------------------------------------------------------------------------------------------------
+
+To compile copy the Optiboot.c and Makefile files where Optiboot is originally located, mine is at:
+arduino-install-dir\hardware\arduino\bootloaders\optiboot\
+Backup the original files andbefore overwrite both files.
+Then compile by running:
+make atmega328
+make atmega1284p
+
+##License
+GPL 3.0. See License.txt file.
\ No newline at end of file
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/boot.h b/hardware/MySensors/avr/bootloaders/DualOptiboot/boot.h
new file mode 100644
index 0000000..2639cd8
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/boot.h
@@ -0,0 +1,848 @@
+/* Modified to use out for SPM access
+** Peter Knight, Optiboot project http://optiboot.googlecode.com
+**
+** Todo: Tidy up
+**
+** "_short" routines execute 1 cycle faster and use 1 less word of flash
+** by using "out" instruction instead of "sts".
+**
+** Additional elpm variants that trust the value of RAMPZ
+*/
+
+/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Eric B. Weddington
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+/* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */
+
+#ifndef _AVR_BOOT_H_
+#define _AVR_BOOT_H_ 1
+
+/** \file */
+/** \defgroup avr_boot : Bootloader Support Utilities
+ \code
+ #include
+ #include
+ \endcode
+
+ The macros in this module provide a C language interface to the
+ bootloader support functionality of certain AVR processors. These
+ macros are designed to work with all sizes of flash memory.
+
+ Global interrupts are not automatically disabled for these macros. It
+ is left up to the programmer to do this. See the code example below.
+ Also see the processor datasheet for caveats on having global interrupts
+ enabled during writing of the Flash.
+
+ \note Not all AVR processors provide bootloader support. See your
+ processor datasheet to see if it provides bootloader support.
+
+ \todo From email with Marek: On smaller devices (all except ATmega64/128),
+ __SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
+ instructions - since the boot loader has a limited size, this could be an
+ important optimization.
+
+ \par API Usage Example
+ The following code shows typical usage of the boot API.
+
+ \code
+ #include
+ #include
+ #include
+
+ void boot_program_page (uint32_t page, uint8_t *buf)
+ {
+ uint16_t i;
+ uint8_t sreg;
+
+ // Disable interrupts.
+
+ sreg = SREG;
+ cli();
+
+ eeprom_busy_wait ();
+
+ boot_page_erase (page);
+ boot_spm_busy_wait (); // Wait until the memory is erased.
+
+ for (i=0; i
+#include
+#include
+#include
+
+/* Check for SPM Control Register in processor. */
+#if defined (SPMCSR)
+# define __SPM_REG SPMCSR
+#elif defined (SPMCR)
+# define __SPM_REG SPMCR
+#else
+# error AVR processor does not provide bootloader support!
+#endif
+
+
+/* Check for SPM Enable bit. */
+#if defined(SPMEN)
+# define __SPM_ENABLE SPMEN
+#elif defined(SELFPRGEN)
+# define __SPM_ENABLE SELFPRGEN
+#else
+# error Cannot find SPM Enable bit definition!
+#endif
+
+/** \ingroup avr_boot
+ \def BOOTLOADER_SECTION
+
+ Used to declare a function or variable to be placed into a
+ new section called .bootloader. This section and its contents
+ can then be relocated to any address (such as the bootloader
+ NRWW area) at link-time. */
+
+#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
+
+/* Create common bit definitions. */
+#ifdef ASB
+#define __COMMON_ASB ASB
+#else
+#define __COMMON_ASB RWWSB
+#endif
+
+#ifdef ASRE
+#define __COMMON_ASRE ASRE
+#else
+#define __COMMON_ASRE RWWSRE
+#endif
+
+/* Define the bit positions of the Boot Lock Bits. */
+
+#define BLB12 5
+#define BLB11 4
+#define BLB02 3
+#define BLB01 2
+
+/** \ingroup avr_boot
+ \def boot_spm_interrupt_enable()
+ Enable the SPM interrupt. */
+
+#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
+
+/** \ingroup avr_boot
+ \def boot_spm_interrupt_disable()
+ Disable the SPM interrupt. */
+
+#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
+
+/** \ingroup avr_boot
+ \def boot_is_spm_interrupt()
+ Check if the SPM interrupt is enabled. */
+
+#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
+
+/** \ingroup avr_boot
+ \def boot_rww_busy()
+ Check if the RWW section is busy. */
+
+#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
+
+/** \ingroup avr_boot
+ \def boot_spm_busy()
+ Check if the SPM instruction is busy. */
+
+#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
+
+/** \ingroup avr_boot
+ \def boot_spm_busy_wait()
+ Wait while the SPM instruction is busy. */
+
+#define boot_spm_busy_wait() do{}while(boot_spm_busy())
+
+#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
+#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
+#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
+#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
+#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
+
+#define __boot_page_fill_short(address, data) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r0, %3\n\t" \
+ "out %0, %1\n\t" \
+ "spm\n\t" \
+ "clr r1\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_FILL), \
+ "z" ((uint16_t)address), \
+ "r" ((uint16_t)data) \
+ : "r0" \
+ ); \
+}))
+
+#define __boot_page_fill_normal(address, data) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r0, %3\n\t" \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ "clr r1\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_FILL), \
+ "z" ((uint16_t)address), \
+ "r" ((uint16_t)data) \
+ : "r0" \
+ ); \
+}))
+
+#define __boot_page_fill_alternate(address, data)\
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r0, %3\n\t" \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ ".word 0xffff\n\t" \
+ "nop\n\t" \
+ "clr r1\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_FILL), \
+ "z" ((uint16_t)address), \
+ "r" ((uint16_t)data) \
+ : "r0" \
+ ); \
+}))
+
+#define __boot_page_fill_extended(address, data) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r0, %4\n\t" \
+ "movw r30, %A3\n\t" \
+ "sts %1, %C3\n\t" \
+ "sts %0, %2\n\t" \
+ "spm\n\t" \
+ "clr r1\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "i" (_SFR_MEM_ADDR(RAMPZ)), \
+ "r" ((uint8_t)__BOOT_PAGE_FILL), \
+ "r" ((uint32_t)address), \
+ "r" ((uint16_t)data) \
+ : "r0", "r30", "r31" \
+ ); \
+}))
+
+#define __boot_page_fill_extended_short(address, data) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r0, %4\n\t" \
+ "movw r30, %A3\n\t" \
+ "out %1, %C3\n\t" \
+ "out %0, %2\n\t" \
+ "spm\n\t" \
+ "clr r1\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "i" (_SFR_IO_ADDR(RAMPZ)), \
+ "r" ((uint8_t)__BOOT_PAGE_FILL), \
+ "r" ((uint32_t)address), \
+ "r" ((uint16_t)data) \
+ : "r0", "r30", "r31" \
+ ); \
+}))
+
+#define __boot_page_erase_short(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "out %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_ERASE), \
+ "z" ((uint16_t)address) \
+ ); \
+}))
+
+
+#define __boot_page_erase_normal(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_ERASE), \
+ "z" ((uint16_t)address) \
+ ); \
+}))
+
+#define __boot_page_erase_alternate(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ ".word 0xffff\n\t" \
+ "nop\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_ERASE), \
+ "z" ((uint16_t)address) \
+ ); \
+}))
+
+#define __boot_page_erase_extended(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r30, %A3\n\t" \
+ "sts %1, %C3\n\t" \
+ "sts %0, %2\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "i" (_SFR_MEM_ADDR(RAMPZ)), \
+ "r" ((uint8_t)__BOOT_PAGE_ERASE), \
+ "r" ((uint32_t)address) \
+ : "r30", "r31" \
+ ); \
+}))
+#define __boot_page_erase_extended_short(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r30, %A3\n\t" \
+ "out %1, %C3\n\t" \
+ "out %0, %2\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "i" (_SFR_IO_ADDR(RAMPZ)), \
+ "r" ((uint8_t)__BOOT_PAGE_ERASE), \
+ "r" ((uint32_t)address) \
+ : "r30", "r31" \
+ ); \
+}))
+
+#define __boot_page_write_short(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "out %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_WRITE), \
+ "z" ((uint16_t)address) \
+ ); \
+}))
+
+#define __boot_page_write_normal(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_WRITE), \
+ "z" ((uint16_t)address) \
+ ); \
+}))
+
+#define __boot_page_write_alternate(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ ".word 0xffff\n\t" \
+ "nop\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_PAGE_WRITE), \
+ "z" ((uint16_t)address) \
+ ); \
+}))
+
+#define __boot_page_write_extended(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r30, %A3\n\t" \
+ "sts %1, %C3\n\t" \
+ "sts %0, %2\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "i" (_SFR_MEM_ADDR(RAMPZ)), \
+ "r" ((uint8_t)__BOOT_PAGE_WRITE), \
+ "r" ((uint32_t)address) \
+ : "r30", "r31" \
+ ); \
+}))
+#define __boot_page_write_extended_short(address) \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "movw r30, %A3\n\t" \
+ "out %1, %C3\n\t" \
+ "out %0, %2\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "i" (_SFR_IO_ADDR(RAMPZ)), \
+ "r" ((uint8_t)__BOOT_PAGE_WRITE), \
+ "r" ((uint32_t)address) \
+ : "r30", "r31" \
+ ); \
+}))
+
+#define __boot_rww_enable_short() \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "out %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_RWW_ENABLE) \
+ ); \
+}))
+
+#define __boot_rww_enable() \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_RWW_ENABLE) \
+ ); \
+}))
+
+#define __boot_rww_enable_alternate() \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ ".word 0xffff\n\t" \
+ "nop\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_RWW_ENABLE) \
+ ); \
+}))
+
+/* From the mega16/mega128 data sheets (maybe others):
+
+ Bits by SPM To set the Boot Loader Lock bits, write the desired data to
+ R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
+ after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
+ that may prevent the Application and Boot Loader section from any
+ software update by the MCU.
+
+ If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
+ will be programmed if an SPM instruction is executed within four cycles
+ after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is
+ don't care during this operation, but for future compatibility it is
+ recommended to load the Z-pointer with $0001 (same as used for reading the
+ Lock bits). For future compatibility It is also recommended to set bits 7,
+ 6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the
+ Lock bits the entire Flash can be read during the operation. */
+
+#define __boot_lock_bits_set_short(lock_bits) \
+(__extension__({ \
+ uint8_t value = (uint8_t)(~(lock_bits)); \
+ __asm__ __volatile__ \
+ ( \
+ "ldi r30, 1\n\t" \
+ "ldi r31, 0\n\t" \
+ "mov r0, %2\n\t" \
+ "out %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
+ "r" (value) \
+ : "r0", "r30", "r31" \
+ ); \
+}))
+
+#define __boot_lock_bits_set(lock_bits) \
+(__extension__({ \
+ uint8_t value = (uint8_t)(~(lock_bits)); \
+ __asm__ __volatile__ \
+ ( \
+ "ldi r30, 1\n\t" \
+ "ldi r31, 0\n\t" \
+ "mov r0, %2\n\t" \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
+ "r" (value) \
+ : "r0", "r30", "r31" \
+ ); \
+}))
+
+#define __boot_lock_bits_set_alternate(lock_bits) \
+(__extension__({ \
+ uint8_t value = (uint8_t)(~(lock_bits)); \
+ __asm__ __volatile__ \
+ ( \
+ "ldi r30, 1\n\t" \
+ "ldi r31, 0\n\t" \
+ "mov r0, %2\n\t" \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ ".word 0xffff\n\t" \
+ "nop\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
+ "r" (value) \
+ : "r0", "r30", "r31" \
+ ); \
+}))
+
+/*
+ Reading lock and fuse bits:
+
+ Similarly to writing the lock bits above, set BLBSET and SPMEN (or
+ SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an
+ LPM instruction.
+
+ Z address: contents:
+ 0x0000 low fuse bits
+ 0x0001 lock bits
+ 0x0002 extended fuse bits
+ 0x0003 high fuse bits
+
+ Sounds confusing, doesn't it?
+
+ Unlike the macros in pgmspace.h, no need to care for non-enhanced
+ cores here as these old cores do not provide SPM support anyway.
+ */
+
+/** \ingroup avr_boot
+ \def GET_LOW_FUSE_BITS
+ address to read the low fuse bits, using boot_lock_fuse_bits_get
+ */
+#define GET_LOW_FUSE_BITS (0x0000)
+/** \ingroup avr_boot
+ \def GET_LOCK_BITS
+ address to read the lock bits, using boot_lock_fuse_bits_get
+ */
+#define GET_LOCK_BITS (0x0001)
+/** \ingroup avr_boot
+ \def GET_EXTENDED_FUSE_BITS
+ address to read the extended fuse bits, using boot_lock_fuse_bits_get
+ */
+#define GET_EXTENDED_FUSE_BITS (0x0002)
+/** \ingroup avr_boot
+ \def GET_HIGH_FUSE_BITS
+ address to read the high fuse bits, using boot_lock_fuse_bits_get
+ */
+#define GET_HIGH_FUSE_BITS (0x0003)
+
+/** \ingroup avr_boot
+ \def boot_lock_fuse_bits_get(address)
+
+ Read the lock or fuse bits at \c address.
+
+ Parameter \c address can be any of GET_LOW_FUSE_BITS,
+ GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
+
+ \note The lock and fuse bits returned are the physical values,
+ i.e. a bit returned as 0 means the corresponding fuse or lock bit
+ is programmed.
+ */
+#define boot_lock_fuse_bits_get_short(address) \
+(__extension__({ \
+ uint8_t __result; \
+ __asm__ __volatile__ \
+ ( \
+ "ldi r30, %3\n\t" \
+ "ldi r31, 0\n\t" \
+ "out %1, %2\n\t" \
+ "lpm %0, Z\n\t" \
+ : "=r" (__result) \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
+ "M" (address) \
+ : "r0", "r30", "r31" \
+ ); \
+ __result; \
+}))
+
+#define boot_lock_fuse_bits_get(address) \
+(__extension__({ \
+ uint8_t __result; \
+ __asm__ __volatile__ \
+ ( \
+ "ldi r30, %3\n\t" \
+ "ldi r31, 0\n\t" \
+ "sts %1, %2\n\t" \
+ "lpm %0, Z\n\t" \
+ : "=r" (__result) \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
+ "M" (address) \
+ : "r0", "r30", "r31" \
+ ); \
+ __result; \
+}))
+
+/** \ingroup avr_boot
+ \def boot_signature_byte_get(address)
+
+ Read the Signature Row byte at \c address. For some MCU types,
+ this function can also retrieve the factory-stored oscillator
+ calibration bytes.
+
+ Parameter \c address can be 0-0x1f as documented by the datasheet.
+ \note The values are MCU type dependent.
+*/
+
+#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
+
+#define boot_signature_byte_get_short(addr) \
+(__extension__({ \
+ uint16_t __addr16 = (uint16_t)(addr); \
+ uint8_t __result; \
+ __asm__ __volatile__ \
+ ( \
+ "out %1, %2\n\t" \
+ "lpm %0, Z" "\n\t" \
+ : "=r" (__result) \
+ : "i" (_SFR_IO_ADDR(__SPM_REG)), \
+ "r" ((uint8_t) __BOOT_SIGROW_READ), \
+ "z" (__addr16) \
+ ); \
+ __result; \
+}))
+
+#define boot_signature_byte_get(addr) \
+(__extension__({ \
+ uint16_t __addr16 = (uint16_t)(addr); \
+ uint8_t __result; \
+ __asm__ __volatile__ \
+ ( \
+ "sts %1, %2\n\t" \
+ "lpm %0, Z" "\n\t" \
+ : "=r" (__result) \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t) __BOOT_SIGROW_READ), \
+ "z" (__addr16) \
+ ); \
+ __result; \
+}))
+
+/** \ingroup avr_boot
+ \def boot_page_fill(address, data)
+
+ Fill the bootloader temporary page buffer for flash
+ address with data word.
+
+ \note The address is a byte address. The data is a word. The AVR
+ writes data to the buffer a word at a time, but addresses the buffer
+ per byte! So, increment your address by 2 between calls, and send 2
+ data bytes in a word format! The LSB of the data is written to the lower
+ address; the MSB of the data is written to the higher address.*/
+
+/** \ingroup avr_boot
+ \def boot_page_erase(address)
+
+ Erase the flash page that contains address.
+
+ \note address is a byte address in flash, not a word address. */
+
+/** \ingroup avr_boot
+ \def boot_page_write(address)
+
+ Write the bootloader temporary page buffer
+ to flash page that contains address.
+
+ \note address is a byte address in flash, not a word address. */
+
+/** \ingroup avr_boot
+ \def boot_rww_enable()
+
+ Enable the Read-While-Write memory section. */
+
+/** \ingroup avr_boot
+ \def boot_lock_bits_set(lock_bits)
+
+ Set the bootloader lock bits.
+
+ \param lock_bits A mask of which Boot Loader Lock Bits to set.
+
+ \note In this context, a 'set bit' will be written to a zero value.
+ Note also that only BLBxx bits can be programmed by this command.
+
+ For example, to disallow the SPM instruction from writing to the Boot
+ Loader memory section of flash, you would use this macro as such:
+
+ \code
+ boot_lock_bits_set (_BV (BLB11));
+ \endcode
+
+ \note Like any lock bits, the Boot Loader Lock Bits, once set,
+ cannot be cleared again except by a chip erase which will in turn
+ also erase the boot loader itself. */
+
+/* Normal versions of the macros use 16-bit addresses.
+ Extended versions of the macros use 32-bit addresses.
+ Alternate versions of the macros use 16-bit addresses and require special
+ instruction sequences after LPM.
+
+ FLASHEND is defined in the ioXXXX.h file.
+ USHRT_MAX is defined in . */
+
+#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
+ || defined(__AVR_ATmega323__)
+
+/* Alternate: ATmega161/163/323 and 16 bit address */
+#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
+#define boot_page_erase(address) __boot_page_erase_alternate(address)
+#define boot_page_write(address) __boot_page_write_alternate(address)
+#define boot_rww_enable() __boot_rww_enable_alternate()
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
+
+#elif (FLASHEND > USHRT_MAX)
+
+/* Extended: >16 bit address */
+#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
+#define boot_page_erase(address) __boot_page_erase_extended_short(address)
+#define boot_page_write(address) __boot_page_write_extended_short(address)
+#define boot_rww_enable() __boot_rww_enable_short()
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
+
+#else
+
+/* Normal: 16 bit address */
+#define boot_page_fill(address, data) __boot_page_fill_short(address, data)
+#define boot_page_erase(address) __boot_page_erase_short(address)
+#define boot_page_write(address) __boot_page_write_short(address)
+#define boot_rww_enable() __boot_rww_enable_short()
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
+
+#endif
+
+/** \ingroup avr_boot
+
+ Same as boot_page_fill() except it waits for eeprom and spm operations to
+ complete before filling the page. */
+
+#define boot_page_fill_safe(address, data) \
+do { \
+ boot_spm_busy_wait(); \
+ eeprom_busy_wait(); \
+ boot_page_fill(address, data); \
+} while (0)
+
+/** \ingroup avr_boot
+
+ Same as boot_page_erase() except it waits for eeprom and spm operations to
+ complete before erasing the page. */
+
+#define boot_page_erase_safe(address) \
+do { \
+ boot_spm_busy_wait(); \
+ eeprom_busy_wait(); \
+ boot_page_erase (address); \
+} while (0)
+
+/** \ingroup avr_boot
+
+ Same as boot_page_write() except it waits for eeprom and spm operations to
+ complete before writing the page. */
+
+#define boot_page_write_safe(address) \
+do { \
+ boot_spm_busy_wait(); \
+ eeprom_busy_wait(); \
+ boot_page_write (address); \
+} while (0)
+
+/** \ingroup avr_boot
+
+ Same as boot_rww_enable() except waits for eeprom and spm operations to
+ complete before enabling the RWW mameory. */
+
+#define boot_rww_enable_safe() \
+do { \
+ boot_spm_busy_wait(); \
+ eeprom_busy_wait(); \
+ boot_rww_enable(); \
+} while (0)
+
+/** \ingroup avr_boot
+
+ Same as boot_lock_bits_set() except waits for eeprom and spm operations to
+ complete before setting the lock bits. */
+
+#define boot_lock_bits_set_safe(lock_bits) \
+do { \
+ boot_spm_busy_wait(); \
+ eeprom_busy_wait(); \
+ boot_lock_bits_set (lock_bits); \
+} while (0)
+
+#endif /* _AVR_BOOT_H_ */
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot.c b/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot.c
new file mode 100644
index 0000000..a527c28
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot.c
@@ -0,0 +1,1068 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// DualOptiboot
+// Optiboot based custom bootloader for Moteino
+// Enables wireless programming of Moteino wireless arduino clone
+// Copyright Felix Rusu (2013), felix@lowpowerlab.com
+// http://lowpowerlab.com/Moteino
+//
+//////////////////////////////////////////////////////////////////////////
+//
+// 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Licence can be viewed at
+// http://www.fsf.org/licenses/gpl.txt
+//
+// Please maintain this license information along with authorship
+// and copyright notices in any redistribution of this code
+//
+//////////////////////////////////////////////////////////////////////////
+//
+// This Optiboot version is modified to add the capability of reflashing
+// from an external SPI flash memory chip. As configured this will work
+// with Moteino (www.lowpowerlab.com/Moteino) provided a SPI flash chip
+// is present on the dedicated onboard footprint.
+// Summary of how this Optiboot version works:
+// - it looks for an external flash chip
+// - if one is found (SPI returns valid data) it will further look
+// for a new sketch flash image signature and size
+// starting at address 0: FLXIMG:NN:XXXXXXXXXXX
+// where: - 'FLXIMG' is fixed signature indicating FLASH chip
+// contains a valid new flash image to be burned
+// - 'NN' are 2 size bytes (uint_16) indicating how long the
+// new flash image is (how many bytes to read), max 65536Bytes
+// - 'XXXXXX' are the de-hexified bytes of the flash
+// pages to be burned
+// - ':' colons have fixed positions (delimiters)
+// - if no valid signature/size are found, it will skip and
+// function as it normally would (listen to STK500 protocol on serial port)
+//
+// The added code will result in a compiled size of just under 1kb
+// (Originally Optiboot takes just under 0.5kb)
+// - Examples at: http://lowpowerlab.com/blog/category/moteino/wireless-programming/
+// - Tested on atmega328P and atmega644/1284P
+// - Limited to 31K sketches for atmega328p and 64K sketches for atmega1284P.
+//////////////////////////////////////////////////////////////////////////
+/**********************************************************/
+/* Optiboot bootloader for Arduino */
+/* */
+/* http://optiboot.googlecode.com */
+/* */
+/* Arduino-maintained version : See README.TXT */
+/* http://code.google.com/p/arduino/ */
+/* It is the intent that changes not relevant to the */
+/* Arduino production envionment get moved from the */
+/* optiboot project to the arduino project in "lumps." */
+/* */
+/* Heavily optimised bootloader that is faster and */
+/* smaller than the Arduino standard bootloader */
+/* */
+/* Enhancements: */
+/* Fits in 512 bytes, saving 1.5K of code space */
+/* Background page erasing speeds up programming */
+/* Higher baud rate speeds up programming */
+/* Written almost entirely in C */
+/* Customisable timeout with accurate timeconstant */
+/* Optional virtual UART. No hardware UART required. */
+/* Optional virtual boot partition for devices without. */
+/* */
+/* What you lose: */
+/* Implements a skeleton STK500 protocol which is */
+/* missing several features including EEPROM */
+/* programming and non-page-aligned writes */
+/* High baud rate breaks compatibility with standard */
+/* Arduino flash settings */
+/* */
+/* Fully supported: */
+/* ATmega168 based devices (Diecimila etc) */
+/* ATmega328P based devices (Duemilanove etc) */
+/* */
+/* Beta test (believed working.) */
+/* ATmega8 based devices (Arduino legacy) */
+/* ATmega328 non-picopower devices */
+/* ATmega644P based devices (Sanguino) */
+/* ATmega1284P based devices */
+/* ATmega1280 based devices (Arduino Mega) */
+/* */
+/* Alpha test */
+/* ATmega32 */
+/* */
+/* Work in progress: */
+/* ATtiny84 based devices (Luminet) */
+/* */
+/* Does not support: */
+/* USB based devices (eg. Teensy, Leonardo) */
+/* */
+/* Assumptions: */
+/* The code makes several assumptions that reduce the */
+/* code size. They are all true after a hardware reset, */
+/* but may not be true if the bootloader is called by */
+/* other means or on other hardware. */
+/* No interrupts can occur */
+/* UART and Timer 1 are set to their reset state */
+/* SP points to RAMEND */
+/* */
+/* Code builds on code, libraries and optimisations from: */
+/* stk500boot.c by Jason P. Kyle */
+/* Arduino bootloader http://arduino.cc */
+/* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
+/* avr-libc project http://nongnu.org/avr-libc */
+/* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
+/* AVR305 Atmel Application Note */
+/* */
+/* 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/* Licence can be viewed at */
+/* http://www.fsf.org/licenses/gpl.txt */
+/* */
+/**********************************************************/
+
+
+/**********************************************************/
+/* */
+/* Optional defines: */
+/* */
+/**********************************************************/
+/* */
+/* BIG_BOOT: */
+/* Build a 1k bootloader, not 512 bytes. This turns on */
+/* extra functionality. */
+/* */
+/* BAUD_RATE: */
+/* Set bootloader baud rate. */
+/* */
+/* LUDICROUS_SPEED: */
+/* 230400 baud :-) */
+/* */
+/* SOFT_UART: */
+/* Use AVR305 soft-UART instead of hardware UART. */
+/* */
+/* LED_START_FLASHES: */
+/* Number of LED flashes on bootup. */
+/* */
+/* LED_DATA_FLASH: */
+/* Flash LED when transferring data. For boards without */
+/* TX or RX LEDs, or for people who like blinky lights. */
+/* */
+/* SUPPORT_EEPROM: */
+/* Support reading and writing from EEPROM. This is not */
+/* used by Arduino, so off by default. */
+/* */
+/* TIMEOUT_MS: */
+/* Bootloader timeout period, in milliseconds. */
+/* 500,1000,2000,4000,8000 supported. */
+/* */
+/* UART: */
+/* UART number (0..n) for devices with more than */
+/* one hardware uart (644P, 1284P, etc) */
+/* */
+/**********************************************************/
+
+/**********************************************************/
+/* Version Numbers! */
+/* */
+/* Arduino Optiboot now includes this Version number in */
+/* the source and object code. */
+/* */
+/* Version 3 was released as zip from the optiboot */
+/* repository and was distributed with Arduino 0022. */
+/* Version 4 starts with the arduino repository commit */
+/* that brought the arduino repository up-to-date with */
+/* the optiboot source tree changes since v3. */
+/* Version 5 was created at the time of the new Makefile */
+/* structure (Mar, 2013), even though no binaries changed*/
+/* It would be good if versions implemented outside the */
+/* official repository used an out-of-seqeunce version */
+/* number (like 104.6 if based on based on 4.5) to */
+/* prevent collisions. */
+/* */
+/**********************************************************/
+
+/**********************************************************/
+/* Edit History: */
+/* */
+/* Mar 2013 */
+/* 5.0 WestfW: Major Makefile restructuring. */
+/* See Makefile and pin_defs.h */
+/* (no binary changes) */
+/* */
+/* 4.6 WestfW/Pito: Add ATmega32 support */
+/* 4.6 WestfW/radoni: Don't set LED_PIN as an output if */
+/* not used. (LED_START_FLASHES = 0) */
+/* Jan 2013 */
+/* 4.6 WestfW/dkinzer: use autoincrement lpm for read */
+/* 4.6 WestfW/dkinzer: pass reset cause to app in R2 */
+/* Mar 2012 */
+/* 4.5 WestfW: add infrastructure for non-zero UARTS. */
+/* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
+/* Jan 2012: */
+/* 4.5 WestfW: fix NRWW value for m1284. */
+/* 4.4 WestfW: use attribute OS_main instead of naked for */
+/* main(). This allows optimizations that we */
+/* count on, which are prohibited in naked */
+/* functions due to PR42240. (keeps us less */
+/* than 512 bytes when compiler is gcc4.5 */
+/* (code from 4.3.2 remains the same.) */
+/* 4.4 WestfW and Maniacbug: Add m1284 support. This */
+/* does not change the 328 binary, so the */
+/* version number didn't change either. (?) */
+/* June 2011: */
+/* 4.4 WestfW: remove automatic soft_uart detect (didn't */
+/* know what it was doing or why.) Added a */
+/* check of the calculated BRG value instead. */
+/* Version stays 4.4; existing binaries are */
+/* not changed. */
+/* 4.4 WestfW: add initialization of address to keep */
+/* the compiler happy. Change SC'ed targets. */
+/* Return the SW version via READ PARAM */
+/* 4.3 WestfW: catch framing errors in getch(), so that */
+/* AVRISP works without HW kludges. */
+/* http://code.google.com/p/arduino/issues/detail?id=368n*/
+/* 4.2 WestfW: reduce code size, fix timeouts, change */
+/* verifySpace to use WDT instead of appstart */
+/* 4.1 WestfW: put version number in binary. */
+/**********************************************************/
+
+#define LED_DATA_FLASH 1
+#define OPTIBOOT_MAJVER 5
+#define OPTIBOOT_MINVER 0
+
+#define MAKESTR(a) #a
+#define MAKEVER(a, b) MAKESTR(a*256+b)
+
+asm(" .section .version\n"
+ "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
+ " .section .text\n");
+
+#include
+#include
+#include
+
+// uses sts instructions, but this version uses out instructions
+// This saves cycles and program memory.
+#include "boot.h"
+
+
+// We don't use as those routines have interrupt overhead we don't need.
+
+#include "pin_defs.h"
+#include "stk500.h"
+
+#ifndef LED_START_FLASHES
+#define LED_START_FLASHES 1
+#endif
+
+#ifdef LUDICROUS_SPEED
+#define BAUD_RATE 230400L
+#endif
+
+/* set the UART baud rate defaults */
+#ifndef BAUD_RATE
+#if F_CPU >= 8000000L
+#define BAUD_RATE 115200L // Highest rate Avrdude win32 will support
+#elsif F_CPU >= 1000000L
+#define BAUD_RATE 9600L // 19200 also supported, but with significant error
+#elsif F_CPU >= 128000L
+#define BAUD_RATE 4800L // Good for 128kHz internal RC
+#else
+#define BAUD_RATE 1200L // Good even at 32768Hz
+#endif
+#endif
+
+#ifndef UART
+#define UART 0
+#endif
+
+#define BAUD_SETTING (( (F_CPU + BAUD_RATE * 4L) / ((BAUD_RATE * 8L))) - 1 )
+#define BAUD_ACTUAL (F_CPU/(8 * ((BAUD_SETTING)+1)))
+#define BAUD_ERROR (( 100*(BAUD_RATE - BAUD_ACTUAL) ) / BAUD_RATE)
+
+#if BAUD_ERROR >= 5
+#error BAUD_RATE error greater than 5%
+#elif BAUD_ERROR <= -5
+#error BAUD_RATE error greater than -5%
+#elif BAUD_ERROR >= 2
+#warning BAUD_RATE error greater than 2%
+#elif BAUD_ERROR <= -2
+#warning BAUD_RATE error greater than -2%
+#endif
+
+#if 0
+/* Switch in soft UART for hard baud rates */
+/*
+ * I don't understand what this was supposed to accomplish, where the
+ * constant "280" came from, or why automatically (and perhaps unexpectedly)
+ * switching to a soft uart is a good thing, so I'm undoing this in favor
+ * of a range check using the same calc used to config the BRG...
+ */
+#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
+#ifndef SOFT_UART
+#define SOFT_UART
+#endif
+#endif
+#else // 0
+#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
+#error Unachievable baud rate (too slow) BAUD_RATE
+#endif // baud rate slow check
+#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
+#error Unachievable baud rate (too fast) BAUD_RATE
+#endif // baud rate fastn check
+#endif
+
+/* Watchdog settings */
+#define WATCHDOG_OFF (0)
+#define WATCHDOG_16MS (_BV(WDE))
+#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
+#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
+#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
+#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
+#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
+#ifndef __AVR_ATmega8__
+#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
+#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
+#endif
+
+/* Function Prototypes */
+/* The main function is in init9, which removes the interrupt vector table */
+/* we don't need. It is also 'naked', which means the compiler does not */
+/* generate any entry or exit code itself. */
+int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9")));
+void putch(char);
+uint8_t getch(void);
+static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
+void verifySpace();
+static inline void flash_led(uint8_t);
+uint8_t getLen();
+static inline void watchdogReset();
+void watchdogConfig(uint8_t x);
+#ifdef SOFT_UART
+void uartDelay() __attribute__ ((naked));
+#endif
+void appStart(uint8_t rstFlags) __attribute__ ((naked));
+
+/*
+ * NRWW memory
+ * Addresses below NRWW (Non-Read-While-Write) can be programmed while
+ * continuing to run code from flash, slightly speeding up programming
+ * time. Beware that Atmel data sheets specify this as a WORD address,
+ * while optiboot will be comparing against a 16-bit byte address. This
+ * means that on a part with 128kB of memory, the upper part of the lower
+ * 64k will get NRWW processing as well, even though it doesn't need it.
+ * That's OK. In fact, you can disable the overlapping processing for
+ * a part entirely by setting NRWWSTART to zero. This reduces code
+ * space a bit, at the expense of being slightly slower, overall.
+ *
+ * RAMSTART should be self-explanatory. It's bigger on parts with a
+ * lot of peripheral registers.
+ */
+#if defined(__AVR_ATmega168__)
+#define RAMSTART (0x100)
+#define NRWWSTART (0x3800)
+#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32__)
+#define RAMSTART (0x100)
+#define NRWWSTART (0x7000)
+#elif defined (__AVR_ATmega644P__)
+#define RAMSTART (0x100)
+#define NRWWSTART (0xE000)
+// correct for a bug in avr-libc
+#undef SIGNATURE_2
+#define SIGNATURE_2 0x0A
+#elif defined (__AVR_ATmega1284P__)
+#define RAMSTART (0x100)
+#define NRWWSTART (0xE000)
+#elif defined(__AVR_ATtiny84__)
+#define RAMSTART (0x100)
+#define NRWWSTART (0x0000)
+#elif defined(__AVR_ATmega1280__)
+#define RAMSTART (0x200)
+#define NRWWSTART (0xE000)
+#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
+#define RAMSTART (0x100)
+#define NRWWSTART (0x1800)
+#endif
+
+/* C zero initialises all global variables. However, that requires */
+/* These definitions are NOT zero initialised, but that doesn't matter */
+/* This allows us to drop the zero init code, saving us memory */
+#define buff ((uint8_t*)(RAMSTART))
+#ifdef VIRTUAL_BOOT_PARTITION
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/*
+ * Handle devices with up to 4 uarts (eg m1280.) Rather inelegantly.
+ * Note that mega8/m32 still needs special handling, because ubrr is handled
+ * differently.
+ */
+#if UART == 0
+# define UART_SRA UCSR0A
+# define UART_SRB UCSR0B
+# define UART_SRC UCSR0C
+# define UART_SRL UBRR0L
+# define UART_UDR UDR0
+#elif UART == 1
+#if !defined(UDR1)
+#error UART == 1, but no UART1 on device
+#endif
+# define UART_SRA UCSR1A
+# define UART_SRB UCSR1B
+# define UART_SRC UCSR1C
+# define UART_SRL UBRR1L
+# define UART_UDR UDR1
+#elif UART == 2
+#if !defined(UDR2)
+#error UART == 2, but no UART2 on device
+#endif
+# define UART_SRA UCSR2A
+# define UART_SRB UCSR2B
+# define UART_SRC UCSR2C
+# define UART_SRL UBRR2L
+# define UART_UDR UDR2
+#elif UART == 3
+#if !defined(UDR1)
+#error UART == 3, but no UART3 on device
+#endif
+# define UART_SRA UCSR3A
+# define UART_SRB UCSR3B
+# define UART_SRC UCSR3C
+# define UART_SRL UBRR3L
+# define UART_UDR UDR3
+#endif
+
+/******************* SPI FLASH Code **********************************/
+// This code will handle the reading/erasing the external SPI FLASH memory
+// assumed to have the SPI_CS on D8 on Moteino (Atmega328P)
+#define SPI_MODE0 0x00
+#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
+#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
+#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
+#define SPI_CLOCK_DIV2 0x04
+
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
+ #define FLASHSS_DDR DDRB
+ #define FLASHSS_PORT PORTB
+ #define FLASHSS PINB0
+ #define SS PINB2
+#elif defined (__AVR_ATmega1284P__) || defined (__AVR_ATmega644P__)
+ #define FLASHSS_DDR DDRC
+ #define FLASHSS_PORT PORTC
+ #define FLASHSS PINC7
+ #define SS PINB4
+#endif
+
+#define FLASH_SELECT { FLASHSS_PORT &= ~(_BV(FLASHSS)); }
+#define FLASH_UNSELECT { FLASHSS_PORT |= _BV(FLASHSS); }
+
+#define SPIFLASH_STATUSWRITE 0x01 // write status register
+#define SPIFLASH_STATUSREAD 0x05 // read status register
+#define SPIFLASH_WRITEENABLE 0x06 // write enable
+#define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency)
+#define SPIFLASH_BLOCKERASE_32K 0x52 // erase one 32K block of flash memory
+#define SPIFLASH_BLOCKERASE_64K 0xD8 // erase one 32K block of flash memory
+#define SPIFLASH_JEDECID 0x9F // read JEDEC ID
+//#define DEBUG_ON // uncomment to enable Serial debugging
+ // (will output different characters depending on which path the bootloader takes)
+
+uint8_t SPI_transfer(uint8_t _data) {
+ SPDR = _data;
+ while (!(SPSR & _BV(SPIF)));
+ return SPDR;
+}
+
+uint8_t FLASH_busy()
+{
+ FLASH_SELECT;
+ SPI_transfer(SPIFLASH_STATUSREAD);
+ uint8_t status = SPI_transfer(0);
+ FLASH_UNSELECT;
+ return status & 1;
+}
+
+void FLASH_command(uint8_t cmd, uint8_t isWrite){
+ if (isWrite)
+ {
+ FLASH_command(SPIFLASH_WRITEENABLE, 0); // Write Enable
+ FLASH_UNSELECT;
+ }
+ while(FLASH_busy()); //wait for chip to become available
+ FLASH_SELECT;
+ SPI_transfer(cmd);
+}
+
+uint8_t FLASH_readByte(uint32_t addr) {
+ FLASH_command(SPIFLASH_ARRAYREADLOWFREQ, 0);
+ SPI_transfer(addr >> 16);
+ SPI_transfer(addr >> 8);
+ SPI_transfer(addr);
+ //SPI.transfer(0); //"dont care", needed with SPIFLASH_ARRAYREAD command only
+ uint8_t result = SPI_transfer(0);
+ FLASH_UNSELECT;
+ return result;
+}
+
+void CheckFlashImage() {
+#ifdef DEBUG_ON
+ putch('F');
+#endif
+ watchdogConfig(WATCHDOG_OFF);
+
+ //SPI INIT
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
+ DDRB |= _BV(FLASHSS) | _BV(SS) | _BV(PB3) | _BV(PB5); //OUTPUTS for FLASH_SS and SS, MOSI, SCK
+ FLASH_UNSELECT; //unselect FLASH chip
+ PORTB |= _BV(SS); //set SS HIGH
+#elif defined (__AVR_ATmega1284P__) || defined (__AVR_ATmega644P__)
+ DDRC |= _BV(FLASHSS); //OUTPUT for FLASH_SS
+ DDRB |= _BV(SS) | _BV(PB5) | _BV(PB7); //OUTPUTS for SS, MOSI, SCK
+ FLASH_UNSELECT; //unselect FLASH chip
+ PORTB |= _BV(SS); //set SS HIGH
+#endif
+
+ //SPCR &= ~(_BV(DORD)); //MSB first
+ //SPCR = (SPCR & ~SPI_MODE_MASK) | SPI_MODE0 ; //SPI MODE 0
+ //SPCR = (SPCR & ~SPI_CLOCK_MASK) | (SPI_CLOCK_DIV2 & SPI_CLOCK_MASK); //clock divider = 2
+ //SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((SPI_CLOCK_DIV2 >> 2) & SPI_2XCLOCK_MASK);
+
+ // Warning: if the SS pin ever becomes a LOW INPUT then SPI automatically switches to Slave, so the data direction of the SS pin MUST be kept as OUTPUT.
+ SPCR |= _BV(MSTR) | _BV(SPE); //enable SPI and set SPI to MASTER mode
+
+ //read first byte of JEDECID, if chip is present it should return a non-0 and non-FF value
+ FLASH_SELECT;
+ SPI_transfer(SPIFLASH_JEDECID);
+ uint8_t deviceId = SPI_transfer(0);
+ FLASH_UNSELECT;
+ if (deviceId==0 || deviceId==0xFF) return;
+
+ //global unprotect
+ FLASH_command(SPIFLASH_STATUSWRITE, 1);
+ SPI_transfer(0);
+ FLASH_UNSELECT;
+
+ //check if any flash image exists on external FLASH chip
+ if (FLASH_readByte(0)=='F' && FLASH_readByte(1)=='L' && FLASH_readByte(2)=='X' && FLASH_readByte(6)==':' && FLASH_readByte(9)==':')
+ {
+#ifdef DEBUG_ON
+ putch('L');
+#endif
+
+ uint16_t imagesize = (FLASH_readByte(7)<<8) | FLASH_readByte(8);
+ if (imagesize%2!=0) return; //basic check that we got even # of bytes
+
+ uint16_t b, i, nextAddress=0;
+
+ LED_PIN |= _BV(LED);
+ for (i=0; i 0
+ // Set up Timer 1 for timeout counter
+ TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+#endif
+#ifndef SOFT_UART
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__)
+ UCSRA = _BV(U2X); //Double speed mode USART
+ UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx
+ UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1
+ UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+#else
+ UART_SRA = _BV(U2X0); //Double speed mode USART0
+ UART_SRB = _BV(RXEN0) | _BV(TXEN0);
+ UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
+ UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+#endif
+#endif
+
+ // Set up watchdog to trigger after 500ms
+ watchdogConfig(WATCHDOG_1S);
+
+#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH)
+ /* Set LED pin as output */
+ LED_DDR |= _BV(LED);
+#endif
+
+#ifdef SOFT_UART
+ /* Set TX pin as output */
+ UART_DDR |= _BV(UART_TX_BIT);
+#endif
+
+#if LED_START_FLASHES > 0
+ /* Flash onboard LED to signal entering of bootloader */
+ flash_led(LED_START_FLASHES * 2);
+#endif
+
+ /* Forever loop */
+ for (;;) {
+ /* get character from UART */
+ ch = getch();
+
+ if(ch == STK_GET_PARAMETER) {
+ unsigned char which = getch();
+ verifySpace();
+ if (which == 0x82) {
+ /*
+ * Send optiboot version as "minor SW version"
+ */
+ putch(OPTIBOOT_MINVER);
+ } else if (which == 0x81) {
+ putch(OPTIBOOT_MAJVER);
+ } else {
+ /*
+ * GET PARAMETER returns a generic 0x03 reply for
+ * other parameters - enough to keep Avrdude happy
+ */
+ putch(0x03);
+ }
+ }
+ else if(ch == STK_SET_DEVICE) {
+ // SET DEVICE is ignored
+ getNch(20);
+ }
+ else if(ch == STK_SET_DEVICE_EXT) {
+ // SET DEVICE EXT is ignored
+ getNch(5);
+ }
+ else if(ch == STK_LOAD_ADDRESS) {
+ // LOAD ADDRESS
+ uint16_t newAddress;
+ newAddress = getch();
+ newAddress = (newAddress & 0xff) | (getch() << 8);
+#ifdef RAMPZ
+ // Transfer top bit to RAMPZ
+ RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+ newAddress += newAddress; // Convert from word address to byte address
+ address = newAddress;
+ verifySpace();
+ }
+ else if(ch == STK_UNIVERSAL) {
+ // UNIVERSAL command is ignored
+ getNch(4);
+ putch(0x00);
+ }
+ /* Write memory, length is big endian and is in bytes */
+ else if(ch == STK_PROG_PAGE) {
+ // PROGRAM PAGE - we support flash programming only, not EEPROM
+ uint8_t *bufPtr;
+ uint16_t addrPtr;
+
+ getch(); /* getlen() */
+ length = getch();
+ getch();
+
+ // If we are in RWW section, immediately start page erase
+ if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
+
+ // While that is going on, read in page contents
+ bufPtr = buff;
+ do *bufPtr++ = getch();
+ while (--length);
+
+ // If we are in NRWW section, page erase has to be delayed until now.
+ // Todo: Take RAMPZ into account (not doing so just means that we will
+ // treat the top of both "pages" of flash as NRWW, for a slight speed
+ // decrease, so fixing this is not urgent.)
+ if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
+
+ // Read command terminator, start reply
+ verifySpace();
+
+ // If only a partial page is to be programmed, the erase might not be complete.
+ // So check that here
+ boot_spm_busy_wait();
+
+#ifdef VIRTUAL_BOOT_PARTITION
+ if ((uint16_t)(void*)address == 0) {
+ // This is the reset vector page. We need to live-patch the code so the
+ // bootloader runs.
+ //
+ // Move RESET vector to WDT vector
+ uint16_t vect = buff[0] | (buff[1]<<8);
+ rstVect = vect;
+ wdtVect = buff[8] | (buff[9]<<8);
+ vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
+ buff[8] = vect & 0xff;
+ buff[9] = vect >> 8;
+
+ // Add jump to bootloader at RESET vector
+ buff[0] = 0x7f;
+ buff[1] = 0xce; // rjmp 0x1d00 instruction
+ }
+#endif
+
+ // Copy buffer into programming buffer
+ bufPtr = buff;
+ addrPtr = (uint16_t)(void*)address;
+ ch = SPM_PAGESIZE / 2;
+ do {
+ uint16_t a;
+ a = *bufPtr++;
+ a |= (*bufPtr++) << 8;
+ __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+ addrPtr += 2;
+ } while (--ch);
+
+ // Write from programming buffer
+ __boot_page_write_short((uint16_t)(void*)address);
+ boot_spm_busy_wait();
+
+#if defined(RWWSRE)
+ // Reenable read access to flash
+ boot_rww_enable();
+#endif
+
+ }
+ /* Read memory block mode, length is big endian. */
+ else if(ch == STK_READ_PAGE) {
+ // READ PAGE - we only read flash
+ getch(); /* getlen() */
+ length = getch();
+ getch();
+
+ verifySpace();
+ do {
+#ifdef VIRTUAL_BOOT_PARTITION
+ // Undo vector patch in bottom page so verify passes
+ if (address == 0) ch=rstVect & 0xff;
+ else if (address == 1) ch=rstVect >> 8;
+ else if (address == 8) ch=wdtVect & 0xff;
+ else if (address == 9) ch=wdtVect >> 8;
+ else ch = pgm_read_byte_near(address);
+ address++;
+#elif defined(RAMPZ)
+ // Since RAMPZ should already be set, we need to use EPLM directly.
+ // Also, we can use the autoincrement version of lpm to update "address"
+ // do putch(pgm_read_byte_near(address++));
+ // while (--length);
+ // read a Flash and increment the address (may increment RAMPZ)
+ __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address): "1" (address));
+#else
+ // read a Flash byte and increment the address
+ __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address): "1" (address));
+#endif
+ putch(ch);
+ } while (--length);
+ }
+
+ /* Get device signature bytes */
+ else if(ch == STK_READ_SIGN) {
+ // READ SIGN - return what Avrdude wants to hear
+ verifySpace();
+ putch(SIGNATURE_0);
+ putch(SIGNATURE_1);
+ putch(SIGNATURE_2);
+ }
+ else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
+ // Adaboot no-wait mod
+ watchdogConfig(WATCHDOG_16MS);
+ verifySpace();
+ }
+ else {
+ // This covers the response to commands like STK_ENTER_PROGMODE
+ verifySpace();
+ }
+ putch(STK_OK);
+ }
+}
+
+void putch(char ch) {
+#ifndef SOFT_UART
+ while (!(UART_SRA & _BV(UDRE0)));
+ UART_UDR = ch;
+#else
+ __asm__ __volatile__ (
+ " com %[ch]\n" // ones complement, carry set
+ " sec\n"
+ "1: brcc 2f\n"
+ " cbi %[uartPort],%[uartBit]\n"
+ " rjmp 3f\n"
+ "2: sbi %[uartPort],%[uartBit]\n"
+ " nop\n"
+ "3: rcall uartDelay\n"
+ " rcall uartDelay\n"
+ " lsr %[ch]\n"
+ " dec %[bitcnt]\n"
+ " brne 1b\n"
+ :
+ :
+ [bitcnt] "d" (10),
+ [ch] "r" (ch),
+ [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
+ [uartBit] "I" (UART_TX_BIT)
+ :
+ "r25"
+ );
+#endif
+}
+
+uint8_t getch(void) {
+ uint8_t ch;
+
+#ifdef LED_DATA_FLASH
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__)
+ LED_PORT ^= _BV(LED);
+#else
+ LED_PIN |= _BV(LED);
+#endif
+#endif
+
+#ifdef SOFT_UART
+ __asm__ __volatile__ (
+ "1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
+ " rjmp 1b\n"
+ " rcall uartDelay\n" // Get to middle of start bit
+ "2: rcall uartDelay\n" // Wait 1 bit period
+ " rcall uartDelay\n" // Wait 1 bit period
+ " clc\n"
+ " sbic %[uartPin],%[uartBit]\n"
+ " sec\n"
+ " dec %[bitCnt]\n"
+ " breq 3f\n"
+ " ror %[ch]\n"
+ " rjmp 2b\n"
+ "3:\n"
+ :
+ [ch] "=r" (ch)
+ :
+ [bitCnt] "d" (9),
+ [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
+ [uartBit] "I" (UART_RX_BIT)
+ :
+ "r25"
+);
+#else
+ while(!(UART_SRA & _BV(RXC0)))
+ ;
+ if (!(UART_SRA & _BV(FE0))) {
+ /*
+ * A Framing Error indicates (probably) that something is talking
+ * to us at the wrong bit rate. Assume that this is because it
+ * expects to be talking to the application, and DON'T reset the
+ * watchdog. This should cause the bootloader to abort and run
+ * the application "soon", if it keeps happening. (Note that we
+ * don't care that an invalid char is returned...)
+ */
+ watchdogReset();
+ }
+
+ ch = UART_UDR;
+#endif
+
+#ifdef LED_DATA_FLASH
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__)
+ LED_PORT ^= _BV(LED);
+#else
+ LED_PIN |= _BV(LED);
+#endif
+#endif
+
+ return ch;
+}
+
+#ifdef SOFT_UART
+// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
+// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
+#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
+
+void uartDelay() {
+ __asm__ __volatile__ (
+ "ldi r25,%[count]\n"
+ "1:dec r25\n"
+ "brne 1b\n"
+ "ret\n"
+ ::[count] "M" (UART_B_VALUE)
+ );
+}
+#endif
+
+void getNch(uint8_t count) {
+ do getch(); while (--count);
+ verifySpace();
+}
+
+void verifySpace() {
+ if (getch() != CRC_EOP) {
+ watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
+ while (1) // and busy-loop so that WD causes
+ ; // a reset and app start.
+ }
+ putch(STK_INSYNC);
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+ do {
+ TCNT1 = -(F_CPU/(1024*16));
+ TIFR1 = _BV(TOV1);
+ while(!(TIFR1 & _BV(TOV1)));
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__)
+ LED_PORT ^= _BV(LED);
+#else
+ LED_PIN |= _BV(LED);
+#endif
+ watchdogReset();
+ } while (--count);
+}
+#endif
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+ __asm__ __volatile__ (
+ "wdr\n"
+ );
+}
+
+void watchdogConfig(uint8_t x) {
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ WDTCSR = x;
+}
+
+void appStart(uint8_t rstFlags) {
+ // save the reset flags in the designated register
+ // This can be saved in a main program by putting code in .init0 (which
+ // executes before normal c init code) to save R2 to a global variable.
+ __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
+
+ watchdogConfig(WATCHDOG_OFF);
+ __asm__ __volatile__ (
+#ifdef VIRTUAL_BOOT_PARTITION
+ // Jump to WDT vector
+ "ldi r30,4\n"
+ "clr r31\n"
+#else
+ // Jump to RST vector
+ "clr r30\n"
+ "clr r31\n"
+#endif
+ "ijmp\n"
+ );
+}
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot_atmega328_pro_8MHz.hex
new file mode 100644
index 0000000..58f396e
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot_atmega328_pro_8MHz.hex
@@ -0,0 +1,67 @@
+:107C00001F92CDB7DEB7112484B714BE81FD06C024
+:107C100083FF03C08983F4D08981E3D185E0809319
+:107C2000810082E08093C00088E18093C10096E0EB
+:107C30009093C20090E19093C400809360008EE026
+:107C4000809360003B9A86E028E13EEF91E030931C
+:107C500085002093840096BBB09BFECF339AA895F5
+:107C60008150A9F7612C712C08E128E0F22EEE2456
+:107C7000E39435E0D32E41E1C42E13E08BD181345F
+:107C800069F488D1898394D189818238F9F0813867
+:107C900011F485E001C083E076D17BC0823411F419
+:107CA00084E103C0853419F485E08ED172C0853536
+:107CB00049F470D1B82E6ED16B2C712C782A660CD9
+:107CC000771C66C0863521F484E07ED180E0E4CF65
+:107CD000843609F03FC05ED15DD1982E5BD161142E
+:107CE00080E7780618F4F30117BFE895A12CBB24B0
+:107CF000B39450D1F50181935F019E12FACF6114C4
+:107D0000F0E77F0618F0F30117BFE89551D107B6E9
+:107D100000FCFDCFA301A0E0B1E08C9112969D0183
+:107D200021503109F901208190E0922BFA010C01D8
+:107D3000E7BEE89511244E5F5F4FA038F1E0BF0722
+:107D400061F7F301D7BEE89507B600FCFDCFC7BECB
+:107D5000E8951FC0843769F41DD11CD1B82E1AD103
+:107D600027D1F30185913F010ED1BA94B110F9CF1B
+:107D700010C0853739F41CD18EE105D185E903D1D6
+:107D80008FE08ACF813521F400936000F09260008B
+:107D90000FD180E1F8D072CF8EBD0DB407FEFDCFBC
+:107DA0008EB50895289885E0F7DF80E0F5DF289A02
+:107DB00081700895CF93C82F662321F060E086E09C
+:107DC000F9DF289AEFDF8111FDCF28988C2FCF9112
+:107DD000E3CFCF92DF92EF92FF926B017C0160E0E4
+:107DE00083E0E8DF8E2DD8DF8D2DD6DF8C2DD4DF1C
+:107DF00080E0D2DF289AFF90EF90DF90CF90089537
+:107E00009F92AF92BF92CF92DF92EF92FF920F9329
+:107E10001F93CF93DF9388E18093600010926000FE
+:107E200084B18D6284B9289A2A9A8CB580658CBDFC
+:107E300028988FE9B1DF80E0AFDF289A81508E3F2C
+:107E400008F095C061E081E0B5DF80E0A5DF289A09
+:107E500060E070E0CB01BDDF863409F088C061E0EE
+:107E600070E080E090E0B5DF8C3409F080C062E023
+:107E700070E080E090E0ADDF883509F078C066E022
+:107E800070E080E090E0A5DF8A3309F070C069E01F
+:107E900070E080E090E09DDF8A3309F068C067E021
+:107EA00070E080E090E095DFC82F68E070E080E04F
+:107EB00090E08FDFD0E0DC2FCC27C82BC0FD57C06F
+:107EC000339AC12CD12C00E010E0BB24B39483E0A2
+:107ED000A82E95E0992E0C171D0770F5B801665F66
+:107EE0007F4F80E090E075DFE82EF12CB801655FF0
+:107EF0007F4F80E090E06DDFF82AF8010701B7BE00
+:107F0000E89511240E5F1F4FC8018F779927892BA1
+:107F100019F00C171D07F9F6F601A7BEE89507B68C
+:107F200000FCFDCFF60197BEE89507B600FCFDCF3B
+:107F3000F0E8CF0ED11CCFCF339881E187BFE89511
+:107F40002A9661E0C130D04810F482E501C088ED86
+:107F500031DF80E021DF80E01FDF80E01DDF289A35
+:107F600088E18093600088E080936000FFCFDF911C
+:107F7000CF911F910F91FF90EF90DF90CF90BF9026
+:107F8000AF909F9008959091C00095FFFCCF809393
+:107F9000C6000895339A8091C00087FFFCCF80917E
+:107FA000C00084FD01C0A8958091C600339A089551
+:107FB000F1DF803239F088E18093600088E08093BF
+:107FC0006000FFCF84E1DFCFCF93C82FE3DFC15044
+:107FD000E9F7CF91EDCFE0E6F0E098E19083808380
+:107FE0000895282EE0E6F0E088E180831082EE27F5
+:047FF000FF270994CA
+:027FFE0000057C
+:0400000300007C007D
+:00000001FF
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot_atmega328_pro_8MHz.lst
new file mode 100644
index 0000000..75a47a7
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/optiboot_atmega328_pro_8MHz.lst
@@ -0,0 +1,787 @@
+
+optiboot_atmega328.elf: filformat elf32-avr
+
+Sektioner:
+Idx Navn Størrelse VMA LMA Filoffs Just
+ 0 .data 00000000 00800100 00007ff4 00000468 2**0
+ CONTENTS, ALLOC, LOAD, DATA
+ 1 .text 000003f4 00007c00 00007c00 00000074 2**1
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 2 .version 00000002 00007ffe 00007ffe 00000468 2**0
+ CONTENTS, READONLY
+ 3 .stab 000011c4 00000000 00000000 0000046c 2**2
+ CONTENTS, READONLY, DEBUGGING
+ 4 .stabstr 00000ddc 00000000 00000000 00001630 2**0
+ CONTENTS, READONLY, DEBUGGING
+ 5 .comment 00000027 00000000 00000000 0000240c 2**0
+ CONTENTS, READONLY
+
+Disassemblering af sektion .text:
+
+00007c00 :
+ 7c00: 1f 92 push r1
+ 7c02: cd b7 in r28, 0x3d ; 61
+ 7c04: de b7 in r29, 0x3e ; 62
+ 7c06: 11 24 eor r1, r1
+ 7c08: 84 b7 in r24, 0x34 ; 52
+ 7c0a: 14 be out 0x34, r1 ; 52
+ 7c0c: 81 fd sbrc r24, 1
+ 7c0e: 06 c0 rjmp .+12 ; 0x7c1c
+ 7c10: 83 ff sbrs r24, 3
+ 7c12: 03 c0 rjmp .+6 ; 0x7c1a
+ 7c14: 89 83 std Y+1, r24 ; 0x01
+ 7c16: f4 d0 rcall .+488 ; 0x7e00
+ 7c18: 89 81 ldd r24, Y+1 ; 0x01
+ 7c1a: e3 d1 rcall .+966 ; 0x7fe2
+ 7c1c: 85 e0 ldi r24, 0x05 ; 5
+ 7c1e: 80 93 81 00 sts 0x0081, r24
+ 7c22: 82 e0 ldi r24, 0x02 ; 2
+ 7c24: 80 93 c0 00 sts 0x00C0, r24
+ 7c28: 88 e1 ldi r24, 0x18 ; 24
+ 7c2a: 80 93 c1 00 sts 0x00C1, r24
+ 7c2e: 96 e0 ldi r25, 0x06 ; 6
+ 7c30: 90 93 c2 00 sts 0x00C2, r25
+ 7c34: 90 e1 ldi r25, 0x10 ; 16
+ 7c36: 90 93 c4 00 sts 0x00C4, r25
+ 7c3a: 80 93 60 00 sts 0x0060, r24
+ 7c3e: 8e e0 ldi r24, 0x0E ; 14
+ 7c40: 80 93 60 00 sts 0x0060, r24
+ 7c44: 3b 9a sbi 0x07, 3 ; 7
+ 7c46: 86 e0 ldi r24, 0x06 ; 6
+ 7c48: 28 e1 ldi r18, 0x18 ; 24
+ 7c4a: 3e ef ldi r19, 0xFE ; 254
+ 7c4c: 91 e0 ldi r25, 0x01 ; 1
+ 7c4e: 30 93 85 00 sts 0x0085, r19
+ 7c52: 20 93 84 00 sts 0x0084, r18
+ 7c56: 96 bb out 0x16, r25 ; 22
+ 7c58: b0 9b sbis 0x16, 0 ; 22
+ 7c5a: fe cf rjmp .-4 ; 0x7c58
+ 7c5c: 33 9a sbi 0x06, 3 ; 6
+ 7c5e: a8 95 wdr
+ 7c60: 81 50 subi r24, 0x01 ; 1
+ 7c62: a9 f7 brne .-22 ; 0x7c4e
+ 7c64: 61 2c mov r6, r1
+ 7c66: 71 2c mov r7, r1
+ 7c68: 08 e1 ldi r16, 0x18 ; 24
+ 7c6a: 28 e0 ldi r18, 0x08 ; 8
+ 7c6c: f2 2e mov r15, r18
+ 7c6e: ee 24 eor r14, r14
+ 7c70: e3 94 inc r14
+ 7c72: 35 e0 ldi r19, 0x05 ; 5
+ 7c74: d3 2e mov r13, r19
+ 7c76: 41 e1 ldi r20, 0x11 ; 17
+ 7c78: c4 2e mov r12, r20
+ 7c7a: 13 e0 ldi r17, 0x03 ; 3
+ 7c7c: 8b d1 rcall .+790 ; 0x7f94
+ 7c7e: 81 34 cpi r24, 0x41 ; 65
+ 7c80: 69 f4 brne .+26 ; 0x7c9c
+ 7c82: 88 d1 rcall .+784 ; 0x7f94
+ 7c84: 89 83 std Y+1, r24 ; 0x01
+ 7c86: 94 d1 rcall .+808 ; 0x7fb0
+ 7c88: 89 81 ldd r24, Y+1 ; 0x01
+ 7c8a: 82 38 cpi r24, 0x82 ; 130
+ 7c8c: f9 f0 breq .+62 ; 0x7ccc
+ 7c8e: 81 38 cpi r24, 0x81 ; 129
+ 7c90: 11 f4 brne .+4 ; 0x7c96
+ 7c92: 85 e0 ldi r24, 0x05 ; 5
+ 7c94: 01 c0 rjmp .+2 ; 0x7c98
+ 7c96: 83 e0 ldi r24, 0x03 ; 3
+ 7c98: 76 d1 rcall .+748 ; 0x7f86
+ 7c9a: 7b c0 rjmp .+246 ; 0x7d92
+ 7c9c: 82 34 cpi r24, 0x42 ; 66
+ 7c9e: 11 f4 brne .+4 ; 0x7ca4
+ 7ca0: 84 e1 ldi r24, 0x14 ; 20
+ 7ca2: 03 c0 rjmp .+6 ; 0x7caa
+ 7ca4: 85 34 cpi r24, 0x45 ; 69
+ 7ca6: 19 f4 brne .+6 ; 0x7cae
+ 7ca8: 85 e0 ldi r24, 0x05 ; 5
+ 7caa: 8e d1 rcall .+796 ; 0x7fc8
+ 7cac: 72 c0 rjmp .+228 ; 0x7d92
+ 7cae: 85 35 cpi r24, 0x55 ; 85
+ 7cb0: 49 f4 brne .+18 ; 0x7cc4
+ 7cb2: 70 d1 rcall .+736 ; 0x7f94
+ 7cb4: b8 2e mov r11, r24
+ 7cb6: 6e d1 rcall .+732 ; 0x7f94
+ 7cb8: 6b 2c mov r6, r11
+ 7cba: 71 2c mov r7, r1
+ 7cbc: 78 2a or r7, r24
+ 7cbe: 66 0c add r6, r6
+ 7cc0: 77 1c adc r7, r7
+ 7cc2: 66 c0 rjmp .+204 ; 0x7d90
+ 7cc4: 86 35 cpi r24, 0x56 ; 86
+ 7cc6: 21 f4 brne .+8 ; 0x7cd0
+ 7cc8: 84 e0 ldi r24, 0x04 ; 4
+ 7cca: 7e d1 rcall .+764 ; 0x7fc8
+ 7ccc: 80 e0 ldi r24, 0x00 ; 0
+ 7cce: e4 cf rjmp .-56 ; 0x7c98
+ 7cd0: 84 36 cpi r24, 0x64 ; 100
+ 7cd2: 09 f0 breq .+2 ; 0x7cd6
+ 7cd4: 3f c0 rjmp .+126 ; 0x7d54
+ 7cd6: 5e d1 rcall .+700 ; 0x7f94
+ 7cd8: 5d d1 rcall .+698 ; 0x7f94
+ 7cda: 98 2e mov r9, r24
+ 7cdc: 5b d1 rcall .+694 ; 0x7f94
+ 7cde: 61 14 cp r6, r1
+ 7ce0: 80 e7 ldi r24, 0x70 ; 112
+ 7ce2: 78 06 cpc r7, r24
+ 7ce4: 18 f4 brcc .+6 ; 0x7cec
+ 7ce6: f3 01 movw r30, r6
+ 7ce8: 17 bf out 0x37, r17 ; 55
+ 7cea: e8 95 spm
+ 7cec: a1 2c mov r10, r1
+ 7cee: bb 24 eor r11, r11
+ 7cf0: b3 94 inc r11
+ 7cf2: 50 d1 rcall .+672 ; 0x7f94
+ 7cf4: f5 01 movw r30, r10
+ 7cf6: 81 93 st Z+, r24
+ 7cf8: 5f 01 movw r10, r30
+ 7cfa: 9e 12 cpse r9, r30
+ 7cfc: fa cf rjmp .-12 ; 0x7cf2
+ 7cfe: 61 14 cp r6, r1
+ 7d00: f0 e7 ldi r31, 0x70 ; 112
+ 7d02: 7f 06 cpc r7, r31
+ 7d04: 18 f0 brcs .+6 ; 0x7d0c
+ 7d06: f3 01 movw r30, r6
+ 7d08: 17 bf out 0x37, r17 ; 55
+ 7d0a: e8 95 spm
+ 7d0c: 51 d1 rcall .+674 ; 0x7fb0
+ 7d0e: 07 b6 in r0, 0x37 ; 55
+ 7d10: 00 fc sbrc r0, 0
+ 7d12: fd cf rjmp .-6 ; 0x7d0e
+ 7d14: a3 01 movw r20, r6
+ 7d16: a0 e0 ldi r26, 0x00 ; 0
+ 7d18: b1 e0 ldi r27, 0x01 ; 1
+ 7d1a: 8c 91 ld r24, X
+ 7d1c: 12 96 adiw r26, 0x02 ; 2
+ 7d1e: 9d 01 movw r18, r26
+ 7d20: 21 50 subi r18, 0x01 ; 1
+ 7d22: 31 09 sbc r19, r1
+ 7d24: f9 01 movw r30, r18
+ 7d26: 20 81 ld r18, Z
+ 7d28: 90 e0 ldi r25, 0x00 ; 0
+ 7d2a: 92 2b or r25, r18
+ 7d2c: fa 01 movw r30, r20
+ 7d2e: 0c 01 movw r0, r24
+ 7d30: e7 be out 0x37, r14 ; 55
+ 7d32: e8 95 spm
+ 7d34: 11 24 eor r1, r1
+ 7d36: 4e 5f subi r20, 0xFE ; 254
+ 7d38: 5f 4f sbci r21, 0xFF ; 255
+ 7d3a: a0 38 cpi r26, 0x80 ; 128
+ 7d3c: f1 e0 ldi r31, 0x01 ; 1
+ 7d3e: bf 07 cpc r27, r31
+ 7d40: 61 f7 brne .-40 ; 0x7d1a
+ 7d42: f3 01 movw r30, r6
+ 7d44: d7 be out 0x37, r13 ; 55
+ 7d46: e8 95 spm
+ 7d48: 07 b6 in r0, 0x37 ; 55
+ 7d4a: 00 fc sbrc r0, 0
+ 7d4c: fd cf rjmp .-6 ; 0x7d48
+ 7d4e: c7 be out 0x37, r12 ; 55
+ 7d50: e8 95 spm
+ 7d52: 1f c0 rjmp .+62 ; 0x7d92
+ 7d54: 84 37 cpi r24, 0x74 ; 116
+ 7d56: 69 f4 brne .+26 ; 0x7d72
+ 7d58: 1d d1 rcall .+570 ; 0x7f94
+ 7d5a: 1c d1 rcall .+568 ; 0x7f94
+ 7d5c: b8 2e mov r11, r24
+ 7d5e: 1a d1 rcall .+564 ; 0x7f94
+ 7d60: 27 d1 rcall .+590 ; 0x7fb0
+ 7d62: f3 01 movw r30, r6
+ 7d64: 85 91 lpm r24, Z+
+ 7d66: 3f 01 movw r6, r30
+ 7d68: 0e d1 rcall .+540 ; 0x7f86
+ 7d6a: ba 94 dec r11
+ 7d6c: b1 10 cpse r11, r1
+ 7d6e: f9 cf rjmp .-14 ; 0x7d62
+ 7d70: 10 c0 rjmp .+32 ; 0x7d92
+ 7d72: 85 37 cpi r24, 0x75 ; 117
+ 7d74: 39 f4 brne .+14 ; 0x7d84
+ 7d76: 1c d1 rcall .+568 ; 0x7fb0
+ 7d78: 8e e1 ldi r24, 0x1E ; 30
+ 7d7a: 05 d1 rcall .+522 ; 0x7f86
+ 7d7c: 85 e9 ldi r24, 0x95 ; 149
+ 7d7e: 03 d1 rcall .+518 ; 0x7f86
+ 7d80: 8f e0 ldi r24, 0x0F ; 15
+ 7d82: 8a cf rjmp .-236 ; 0x7c98
+ 7d84: 81 35 cpi r24, 0x51 ; 81
+ 7d86: 21 f4 brne .+8 ; 0x7d90
+ 7d88: 00 93 60 00 sts 0x0060, r16
+ 7d8c: f0 92 60 00 sts 0x0060, r15
+ 7d90: 0f d1 rcall .+542 ; 0x7fb0
+ 7d92: 80 e1 ldi r24, 0x10 ; 16
+ 7d94: f8 d0 rcall .+496 ; 0x7f86
+ 7d96: 72 cf rjmp .-284 ; 0x7c7c
+
+00007d98 :
+#define SPIFLASH_JEDECID 0x9F // read JEDEC ID
+//#define DEBUG_ON // uncomment to enable Serial debugging
+ // (will output different characters depending on which path the bootloader takes)
+
+uint8_t SPI_transfer(uint8_t _data) {
+ SPDR = _data;
+ 7d98: 8e bd out 0x2e, r24 ; 46
+ while (!(SPSR & _BV(SPIF)));
+ 7d9a: 0d b4 in r0, 0x2d ; 45
+ 7d9c: 07 fe sbrs r0, 7
+ 7d9e: fd cf rjmp .-6 ; 0x7d9a
+ return SPDR;
+ 7da0: 8e b5 in r24, 0x2e ; 46
+}
+ 7da2: 08 95 ret
+
+00007da4 :
+
+uint8_t FLASH_busy()
+{
+ FLASH_SELECT;
+ 7da4: 28 98 cbi 0x05, 0 ; 5
+ SPI_transfer(SPIFLASH_STATUSREAD);
+ 7da6: 85 e0 ldi r24, 0x05 ; 5
+ 7da8: f7 df rcall .-18 ; 0x7d98
+ 7daa: 80 e0 ldi r24, 0x00 ; 0
+ uint8_t status = SPI_transfer(0);
+ 7dac: f5 df rcall .-22 ; 0x7d98
+ 7dae: 28 9a sbi 0x05, 0 ; 5
+ 7db0: 81 70 andi r24, 0x01 ; 1
+ FLASH_UNSELECT;
+ 7db2: 08 95 ret
+
+00007db4 :
+ return status & 1;
+}
+
+void FLASH_command(uint8_t cmd, uint8_t isWrite){
+ 7db4: cf 93 push r28
+ 7db6: c8 2f mov r28, r24
+ if (isWrite)
+ 7db8: 66 23 and r22, r22
+ 7dba: 21 f0 breq .+8 ; 0x7dc4
+ {
+ FLASH_command(SPIFLASH_WRITEENABLE, 0); // Write Enable
+ 7dbc: 60 e0 ldi r22, 0x00 ; 0
+ 7dbe: 86 e0 ldi r24, 0x06 ; 6
+ 7dc0: f9 df rcall .-14 ; 0x7db4
+ 7dc2: 28 9a sbi 0x05, 0 ; 5
+ FLASH_UNSELECT;
+ 7dc4: ef df rcall .-34 ; 0x7da4
+ }
+ while(FLASH_busy()); //wait for chip to become available
+ 7dc6: 81 11 cpse r24, r1
+ 7dc8: fd cf rjmp .-6 ; 0x7dc4
+ 7dca: 28 98 cbi 0x05, 0 ; 5
+ 7dcc: 8c 2f mov r24, r28
+ FLASH_SELECT;
+ 7dce: cf 91 pop r28
+ SPI_transfer(cmd);
+ 7dd0: e3 cf rjmp .-58 ; 0x7d98
+
+00007dd2 :
+}
+
+uint8_t FLASH_readByte(uint32_t addr) {
+ 7dd2: cf 92 push r12
+ 7dd4: df 92 push r13
+ 7dd6: ef 92 push r14
+ 7dd8: ff 92 push r15
+ 7dda: 6b 01 movw r12, r22
+ 7ddc: 7c 01 movw r14, r24
+ FLASH_command(SPIFLASH_ARRAYREADLOWFREQ, 0);
+ 7dde: 60 e0 ldi r22, 0x00 ; 0
+ 7de0: 83 e0 ldi r24, 0x03 ; 3
+ 7de2: e8 df rcall .-48 ; 0x7db4
+ 7de4: 8e 2d mov r24, r14
+ SPI_transfer(addr >> 16);
+ 7de6: d8 df rcall .-80 ; 0x7d98
+ 7de8: 8d 2d mov r24, r13
+ 7dea: d6 df rcall .-84 ; 0x7d98
+ SPI_transfer(addr >> 8);
+ 7dec: 8c 2d mov r24, r12
+ 7dee: d4 df rcall .-88 ; 0x7d98
+ 7df0: 80 e0 ldi r24, 0x00 ; 0
+ SPI_transfer(addr);
+ 7df2: d2 df rcall .-92 ; 0x7d98
+ 7df4: 28 9a sbi 0x05, 0 ; 5
+ 7df6: ff 90 pop r15
+ //SPI.transfer(0); //"dont care", needed with SPIFLASH_ARRAYREAD command only
+ uint8_t result = SPI_transfer(0);
+ 7df8: ef 90 pop r14
+ 7dfa: df 90 pop r13
+ 7dfc: cf 90 pop r12
+ FLASH_UNSELECT;
+ 7dfe: 08 95 ret
+
+00007e00 :
+ return result;
+}
+
+void CheckFlashImage() {
+ 7e00: 9f 92 push r9
+ 7e02: af 92 push r10
+ 7e04: bf 92 push r11
+ 7e06: cf 92 push r12
+ 7e08: df 92 push r13
+ 7e0a: ef 92 push r14
+ 7e0c: ff 92 push r15
+ 7e0e: 0f 93 push r16
+ 7e10: 1f 93 push r17
+ 7e12: cf 93 push r28
+ 7e14: df 93 push r29
+ "wdr\n"
+ );
+}
+
+void watchdogConfig(uint8_t x) {
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ 7e16: 88 e1 ldi r24, 0x18 ; 24
+ 7e18: 80 93 60 00 sts 0x0060, r24
+ WDTCSR = x;
+ 7e1c: 10 92 60 00 sts 0x0060, r1
+#endif
+ watchdogConfig(WATCHDOG_OFF);
+
+ //SPI INIT
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
+ DDRB |= _BV(FLASHSS) | _BV(SS) | _BV(PB3) | _BV(PB5); //OUTPUTS for FLASH_SS and SS, MOSI, SCK
+ 7e20: 84 b1 in r24, 0x04 ; 4
+ 7e22: 8d 62 ori r24, 0x2D ; 45
+ 7e24: 84 b9 out 0x04, r24 ; 4
+ FLASH_UNSELECT; //unselect FLASH chip
+ 7e26: 28 9a sbi 0x05, 0 ; 5
+ PORTB |= _BV(SS); //set SS HIGH
+ 7e28: 2a 9a sbi 0x05, 2 ; 5
+ //SPCR = (SPCR & ~SPI_MODE_MASK) | SPI_MODE0 ; //SPI MODE 0
+ //SPCR = (SPCR & ~SPI_CLOCK_MASK) | (SPI_CLOCK_DIV2 & SPI_CLOCK_MASK); //clock divider = 2
+ //SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((SPI_CLOCK_DIV2 >> 2) & SPI_2XCLOCK_MASK);
+
+ // Warning: if the SS pin ever becomes a LOW INPUT then SPI automatically switches to Slave, so the data direction of the SS pin MUST be kept as OUTPUT.
+ SPCR |= _BV(MSTR) | _BV(SPE); //enable SPI and set SPI to MASTER mode
+ 7e2a: 8c b5 in r24, 0x2c ; 44
+ 7e2c: 80 65 ori r24, 0x50 ; 80
+ 7e2e: 8c bd out 0x2c, r24 ; 44
+
+ //read first byte of JEDECID, if chip is present it should return a non-0 and non-FF value
+ FLASH_SELECT;
+ 7e30: 28 98 cbi 0x05, 0 ; 5
+ SPI_transfer(SPIFLASH_JEDECID);
+ 7e32: 8f e9 ldi r24, 0x9F ; 159
+ 7e34: b1 df rcall .-158 ; 0x7d98
+ 7e36: 80 e0 ldi r24, 0x00 ; 0
+ uint8_t deviceId = SPI_transfer(0);
+ 7e38: af df rcall .-162 ; 0x7d98
+ 7e3a: 28 9a sbi 0x05, 0 ; 5
+ 7e3c: 81 50 subi r24, 0x01 ; 1
+ FLASH_UNSELECT;
+ 7e3e: 8e 3f cpi r24, 0xFE ; 254
+ if (deviceId==0 || deviceId==0xFF) return;
+ 7e40: 08 f0 brcs .+2 ; 0x7e44
+ 7e42: 95 c0 rjmp .+298 ; 0x7f6e
+ 7e44: 61 e0 ldi r22, 0x01 ; 1
+ 7e46: 81 e0 ldi r24, 0x01 ; 1
+
+ //global unprotect
+ FLASH_command(SPIFLASH_STATUSWRITE, 1);
+ 7e48: b5 df rcall .-150 ; 0x7db4
+ 7e4a: 80 e0 ldi r24, 0x00 ; 0
+ 7e4c: a5 df rcall .-182 ; 0x7d98
+ 7e4e: 28 9a sbi 0x05, 0 ; 5
+ SPI_transfer(0);
+ 7e50: 60 e0 ldi r22, 0x00 ; 0
+ 7e52: 70 e0 ldi r23, 0x00 ; 0
+ 7e54: cb 01 movw r24, r22
+ FLASH_UNSELECT;
+ 7e56: bd df rcall .-134 ; 0x7dd2
+
+ //check if any flash image exists on external FLASH chip
+ if (FLASH_readByte(0)=='F' && FLASH_readByte(1)=='L' && FLASH_readByte(2)=='X' && FLASH_readByte(6)==':' && FLASH_readByte(9)==':')
+ 7e58: 86 34 cpi r24, 0x46 ; 70
+ 7e5a: 09 f0 breq .+2 ; 0x7e5e
+ 7e5c: 88 c0 rjmp .+272 ; 0x7f6e
+ 7e5e: 61 e0 ldi r22, 0x01 ; 1
+ 7e60: 70 e0 ldi r23, 0x00 ; 0
+ 7e62: 80 e0 ldi r24, 0x00 ; 0
+ 7e64: 90 e0 ldi r25, 0x00 ; 0
+ 7e66: b5 df rcall .-150 ; 0x7dd2
+ 7e68: 8c 34 cpi r24, 0x4C ; 76
+ 7e6a: 09 f0 breq .+2 ; 0x7e6e
+ 7e6c: 80 c0 rjmp .+256 ; 0x7f6e
+ 7e6e: 62 e0 ldi r22, 0x02 ; 2
+ 7e70: 70 e0 ldi r23, 0x00 ; 0
+ 7e72: 80 e0 ldi r24, 0x00 ; 0
+ 7e74: 90 e0 ldi r25, 0x00 ; 0
+ 7e76: ad df rcall .-166 ; 0x7dd2
+ 7e78: 88 35 cpi r24, 0x58 ; 88
+ 7e7a: 09 f0 breq .+2 ; 0x7e7e
+ 7e7c: 78 c0 rjmp .+240 ; 0x7f6e
+ 7e7e: 66 e0 ldi r22, 0x06 ; 6
+ 7e80: 70 e0 ldi r23, 0x00 ; 0
+ 7e82: 80 e0 ldi r24, 0x00 ; 0
+ 7e84: 90 e0 ldi r25, 0x00 ; 0
+ 7e86: a5 df rcall .-182 ; 0x7dd2
+ 7e88: 8a 33 cpi r24, 0x3A ; 58
+ 7e8a: 09 f0 breq .+2 ; 0x7e8e
+ 7e8c: 70 c0 rjmp .+224 ; 0x7f6e
+ 7e8e: 69 e0 ldi r22, 0x09 ; 9
+ 7e90: 70 e0 ldi r23, 0x00 ; 0
+ 7e92: 80 e0 ldi r24, 0x00 ; 0
+ 7e94: 90 e0 ldi r25, 0x00 ; 0
+ 7e96: 9d df rcall .-198 ; 0x7dd2
+ 7e98: 8a 33 cpi r24, 0x3A ; 58
+ 7e9a: 09 f0 breq .+2 ; 0x7e9e
+ 7e9c: 68 c0 rjmp .+208 ; 0x7f6e
+ 7e9e: 67 e0 ldi r22, 0x07 ; 7
+ 7ea0: 70 e0 ldi r23, 0x00 ; 0
+ 7ea2: 80 e0 ldi r24, 0x00 ; 0
+ 7ea4: 90 e0 ldi r25, 0x00 ; 0
+ 7ea6: 95 df rcall .-214 ; 0x7dd2
+ 7ea8: c8 2f mov r28, r24
+ 7eaa: 68 e0 ldi r22, 0x08 ; 8
+ 7eac: 70 e0 ldi r23, 0x00 ; 0
+ 7eae: 80 e0 ldi r24, 0x00 ; 0
+ {
+#ifdef DEBUG_ON
+ putch('L');
+#endif
+
+ uint16_t imagesize = (FLASH_readByte(7)<<8) | FLASH_readByte(8);
+ 7eb0: 90 e0 ldi r25, 0x00 ; 0
+ 7eb2: 8f df rcall .-226 ; 0x7dd2
+ 7eb4: d0 e0 ldi r29, 0x00 ; 0
+ 7eb6: dc 2f mov r29, r28
+ 7eb8: cc 27 eor r28, r28
+ 7eba: c8 2b or r28, r24
+ 7ebc: c0 fd sbrc r28, 0
+ 7ebe: 57 c0 rjmp .+174 ; 0x7f6e
+ 7ec0: 33 9a sbi 0x06, 3 ; 6
+ 7ec2: c1 2c mov r12, r1
+ 7ec4: d1 2c mov r13, r1
+ 7ec6: 00 e0 ldi r16, 0x00 ; 0
+ 7ec8: 10 e0 ldi r17, 0x00 ; 0
+ 7eca: bb 24 eor r11, r11
+ 7ecc: b3 94 inc r11
+ 7ece: 83 e0 ldi r24, 0x03 ; 3
+ 7ed0: a8 2e mov r10, r24
+ if (imagesize%2!=0) return; //basic check that we got even # of bytes
+ 7ed2: 95 e0 ldi r25, 0x05 ; 5
+ 7ed4: 99 2e mov r9, r25
+
+ uint16_t b, i, nextAddress=0;
+
+ LED_PIN |= _BV(LED);
+ 7ed6: 0c 17 cp r16, r28
+#endif
+
+ uint16_t imagesize = (FLASH_readByte(7)<<8) | FLASH_readByte(8);
+ if (imagesize%2!=0) return; //basic check that we got even # of bytes
+
+ uint16_t b, i, nextAddress=0;
+ 7ed8: 1d 07 cpc r17, r29
+ 7eda: 70 f5 brcc .+92 ; 0x7f38
+
+ LED_PIN |= _BV(LED);
+ for (i=0; i
+ boot_spm_busy_wait();
+ // Write from programming buffer
+ __boot_page_write_short((uint16_t)(void*)nextAddress ); //(i+2-SPM_PAGESIZE)
+ 7ee8: e8 2e mov r14, r24
+ 7eea: f1 2c mov r15, r1
+ if (imagesize%2!=0) return; //basic check that we got even # of bytes
+
+ uint16_t b, i, nextAddress=0;
+
+ LED_PIN |= _BV(LED);
+ for (i=0; i
+#ifdef DEBUG_ON
+ putch('*');
+#endif
+
+ //read 2 bytes (16 bits) from flash image, transfer them to page buffer
+ b = FLASH_readByte(i+10); // flash image starts at position 10 on the external flash memory: FLX:XX:FLASH_IMAGE_BYTES_HERE...... (XX = two size bytes)
+ 7ef8: f8 2a or r15, r24
+ 7efa: f8 01 movw r30, r16
+ 7efc: 07 01 movw r0, r14
+ 7efe: b7 be out 0x37, r11 ; 55
+ 7f00: e8 95 spm
+ 7f02: 11 24 eor r1, r1
+ 7f04: 0e 5f subi r16, 0xFE ; 254
+ 7f06: 1f 4f sbci r17, 0xFF ; 255
+ 7f08: c8 01 movw r24, r16
+ b |= FLASH_readByte(i+11) << 8; //bytes are stored big endian on external flash, need to flip the bytes to little endian for transfer to internal flash
+ 7f0a: 8f 77 andi r24, 0x7F ; 127
+ 7f0c: 99 27 eor r25, r25
+ 7f0e: 89 2b or r24, r25
+ 7f10: 19 f0 breq .+6 ; 0x7f18
+ 7f12: 0c 17 cp r16, r28
+ __boot_page_fill_short((uint16_t)(void*)i,b);
+ 7f14: 1d 07 cpc r17, r29
+ 7f16: f9 f6 brne .-66 ; 0x7ed6
+ 7f18: f6 01 movw r30, r12
+ 7f1a: a7 be out 0x37, r10 ; 55
+ 7f1c: e8 95 spm
+
+ //when 1 page is full (or we're on the last page), write it to the internal flash memory
+ if ((i+2)%SPM_PAGESIZE==0 || (i+2==imagesize))
+ 7f1e: 07 b6 in r0, 0x37 ; 55
+ 7f20: 00 fc sbrc r0, 0
+ 7f22: fd cf rjmp .-6 ; 0x7f1e
+ 7f24: f6 01 movw r30, r12
+ 7f26: 97 be out 0x37, r9 ; 55
+ 7f28: e8 95 spm
+ 7f2a: 07 b6 in r0, 0x37 ; 55
+ 7f2c: 00 fc sbrc r0, 0
+ 7f2e: fd cf rjmp .-6 ; 0x7f2a
+ 7f30: f0 e8 ldi r31, 0x80 ; 128
+ {
+ __boot_page_erase_short((uint16_t)(void*)nextAddress); //(i+2-SPM_PAGESIZE)
+ 7f32: cf 0e add r12, r31
+ 7f34: d1 1c adc r13, r1
+ 7f36: cf cf rjmp .-98 ; 0x7ed6
+ boot_spm_busy_wait();
+ 7f38: 33 98 cbi 0x06, 3 ; 6
+ 7f3a: 81 e1 ldi r24, 0x11 ; 17
+ 7f3c: 87 bf out 0x37, r24 ; 55
+ // Write from programming buffer
+ __boot_page_write_short((uint16_t)(void*)nextAddress ); //(i+2-SPM_PAGESIZE)
+ 7f3e: e8 95 spm
+ 7f40: 2a 96 adiw r28, 0x0a ; 10
+ 7f42: 61 e0 ldi r22, 0x01 ; 1
+ boot_spm_busy_wait();
+ 7f44: c1 30 cpi r28, 0x01 ; 1
+ 7f46: d0 48 sbci r29, 0x80 ; 128
+ 7f48: 10 f4 brcc .+4 ; 0x7f4e
+ nextAddress += SPM_PAGESIZE;
+ 7f4a: 82 e5 ldi r24, 0x52 ; 82
+ 7f4c: 01 c0 rjmp .+2 ; 0x7f50
+ 7f4e: 88 ed ldi r24, 0xD8 ; 216
+ 7f50: 31 df rcall .-414 ; 0x7db4
+ }
+ }
+ LED_PIN &= ~_BV(LED);
+ 7f52: 80 e0 ldi r24, 0x00 ; 0
+
+#if defined(RWWSRE)
+ // Reenable read access to flash
+ boot_rww_enable();
+ 7f54: 21 df rcall .-446 ; 0x7d98
+ 7f56: 80 e0 ldi r24, 0x00 ; 0
+ 7f58: 1f df rcall .-450 ; 0x7d98
+#ifdef DEBUG_ON
+ putch('E');
+#endif
+
+ //erase the first 32/64K block where flash image resided (atmega328 should be less than 31K, and atmega1284 can be up to 64K)
+ if (imagesize+10<=32768) FLASH_command(SPIFLASH_BLOCKERASE_32K, 1);
+ 7f5a: 80 e0 ldi r24, 0x00 ; 0
+ 7f5c: 1d df rcall .-454 ; 0x7d98
+ 7f5e: 28 9a sbi 0x05, 0 ; 5
+ 7f60: 88 e1 ldi r24, 0x18 ; 24
+ 7f62: 80 93 60 00 sts 0x0060, r24
+ 7f66: 88 e0 ldi r24, 0x08 ; 8
+ else FLASH_command(SPIFLASH_BLOCKERASE_64K, 1);
+ 7f68: 80 93 60 00 sts 0x0060, r24
+ 7f6c: ff cf rjmp .-2 ; 0x7f6c
+ SPI_transfer(0);
+ 7f6e: df 91 pop r29
+ 7f70: cf 91 pop r28
+ 7f72: 1f 91 pop r17
+ SPI_transfer(0);
+ 7f74: 0f 91 pop r16
+ 7f76: ff 90 pop r15
+ 7f78: ef 90 pop r14
+ SPI_transfer(0);
+ 7f7a: df 90 pop r13
+ 7f7c: cf 90 pop r12
+ 7f7e: bf 90 pop r11
+ FLASH_UNSELECT;
+ 7f80: af 90 pop r10
+ "wdr\n"
+ );
+}
+
+void watchdogConfig(uint8_t x) {
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ 7f82: 9f 90 pop r9
+ 7f84: 08 95 ret
+
+00007f86 :
+ }
+}
+
+void putch(char ch) {
+#ifndef SOFT_UART
+ while (!(UART_SRA & _BV(UDRE0)));
+ 7f86: 90 91 c0 00 lds r25, 0x00C0
+ 7f8a: 95 ff sbrs r25, 5
+ 7f8c: fc cf rjmp .-8 ; 0x7f86
+ UART_UDR = ch;
+ 7f8e: 80 93 c6 00 sts 0x00C6, r24
+ 7f92: 08 95 ret
+
+00007f94 :
+
+#ifdef LED_DATA_FLASH
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__)
+ LED_PORT ^= _BV(LED);
+#else
+ LED_PIN |= _BV(LED);
+ 7f94: 33 9a sbi 0x06, 3 ; 6
+ [uartBit] "I" (UART_RX_BIT)
+ :
+ "r25"
+);
+#else
+ while(!(UART_SRA & _BV(RXC0)))
+ 7f96: 80 91 c0 00 lds r24, 0x00C0
+ 7f9a: 87 ff sbrs r24, 7
+ 7f9c: fc cf rjmp .-8 ; 0x7f96
+ ;
+ if (!(UART_SRA & _BV(FE0))) {
+ 7f9e: 80 91 c0 00 lds r24, 0x00C0
+ 7fa2: 84 fd sbrc r24, 4
+ 7fa4: 01 c0 rjmp .+2 ; 0x7fa8
+}
+#endif
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+ __asm__ __volatile__ (
+ 7fa6: a8 95 wdr
+ * don't care that an invalid char is returned...)
+ */
+ watchdogReset();
+ }
+
+ ch = UART_UDR;
+ 7fa8: 80 91 c6 00 lds r24, 0x00C6
+
+#ifdef LED_DATA_FLASH
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__)
+ LED_PORT ^= _BV(LED);
+#else
+ LED_PIN |= _BV(LED);
+ 7fac: 33 9a sbi 0x06, 3 ; 6
+#endif
+#endif
+
+ return ch;
+}
+ 7fae: 08 95 ret
+
+00007fb0 :
+ do getch(); while (--count);
+ verifySpace();
+}
+
+void verifySpace() {
+ if (getch() != CRC_EOP) {
+ 7fb0: f1 df rcall .-30 ; 0x7f94
+ 7fb2: 80 32 cpi r24, 0x20 ; 32
+ 7fb4: 39 f0 breq .+14 ; 0x7fc4
+ 7fb6: 88 e1 ldi r24, 0x18 ; 24
+ "wdr\n"
+ );
+}
+
+void watchdogConfig(uint8_t x) {
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ 7fb8: 80 93 60 00 sts 0x0060, r24
+ 7fbc: 88 e0 ldi r24, 0x08 ; 8
+ WDTCSR = x;
+ 7fbe: 80 93 60 00 sts 0x0060, r24
+ 7fc2: ff cf rjmp .-2 ; 0x7fc2
+
+void verifySpace() {
+ if (getch() != CRC_EOP) {
+ watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
+ while (1) // and busy-loop so that WD causes
+ ; // a reset and app start.
+ 7fc4: 84 e1 ldi r24, 0x14 ; 20
+ }
+ putch(STK_INSYNC);
+ 7fc6: df cf rjmp .-66 ; 0x7f86
+
+00007fc8 :
+ ::[count] "M" (UART_B_VALUE)
+ );
+}
+#endif
+
+void getNch(uint8_t count) {
+ 7fc8: cf 93 push r28
+ 7fca: c8 2f mov r28, r24
+ do getch(); while (--count);
+ 7fcc: e3 df rcall .-58 ; 0x7f94
+ 7fce: c1 50 subi r28, 0x01 ; 1
+ 7fd0: e9 f7 brne .-6 ; 0x7fcc
+ 7fd2: cf 91 pop r28
+ verifySpace();
+}
+ 7fd4: ed cf rjmp .-38 ; 0x7fb0
+
+00007fd6 :
+ "wdr\n"
+ );
+}
+
+void watchdogConfig(uint8_t x) {
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ 7fd6: e0 e6 ldi r30, 0x60 ; 96
+ 7fd8: f0 e0 ldi r31, 0x00 ; 0
+ 7fda: 98 e1 ldi r25, 0x18 ; 24
+ 7fdc: 90 83 st Z, r25
+ WDTCSR = x;
+ 7fde: 80 83 st Z, r24
+ 7fe0: 08 95 ret
+
+00007fe2 :
+
+void appStart(uint8_t rstFlags) {
+ // save the reset flags in the designated register
+ // This can be saved in a main program by putting code in .init0 (which
+ // executes before normal c init code) to save R2 to a global variable.
+ __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
+ 7fe2: 28 2e mov r2, r24
+ "wdr\n"
+ );
+}
+
+void watchdogConfig(uint8_t x) {
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ 7fe4: e0 e6 ldi r30, 0x60 ; 96
+ 7fe6: f0 e0 ldi r31, 0x00 ; 0
+ 7fe8: 88 e1 ldi r24, 0x18 ; 24
+ 7fea: 80 83 st Z, r24
+ WDTCSR = x;
+ 7fec: 10 82 st Z, r1
+ // This can be saved in a main program by putting code in .init0 (which
+ // executes before normal c init code) to save R2 to a global variable.
+ __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
+
+ watchdogConfig(WATCHDOG_OFF);
+ __asm__ __volatile__ (
+ 7fee: ee 27 eor r30, r30
+ 7ff0: ff 27 eor r31, r31
+ 7ff2: 09 94 ijmp
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/pin_defs.h b/hardware/MySensors/avr/bootloaders/DualOptiboot/pin_defs.h
new file mode 100644
index 0000000..30b0a67
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/pin_defs.h
@@ -0,0 +1,742 @@
+/*------------------------------------------------------------------------ */
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
+/*------------------------------------------------------------------------ */
+
+/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove
+ */
+#if !defined(LED)
+#define LED B1 //D9
+#endif
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT PORTD
+#define UART_PIN PIND
+#define UART_DDR DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega32__)
+ //Name conversion R.Wiersma
+ #define UCSR0A UCSRA
+ #define UDR0 UDR
+ #define UDRE0 UDRE
+ #define RXC0 RXC
+ #define FE0 FE
+ #define TIFR1 TIFR
+ #define WDTCSR WDTCR
+#endif
+#if defined(__AVR_ATmega32__)
+ #define WDCE WDTOE
+#endif
+
+/* Luminet support */
+/*------------------------------------------------------------------------ */
+#if defined(__AVR_ATtiny84__)
+/*------------------------------------------------------------------------ */
+/* Red LED is connected to pin PA4 */
+#if !defined(LED)
+#define LED A4
+#endif
+
+/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
+#ifdef SOFT_UART
+#define UART_PORT PORTA
+#define UART_PIN PINA
+#define UART_DDR DDRA
+#define UART_TX_BIT 2
+#define UART_RX_BIT 3
+#endif
+#endif
+
+/*------------------------------------------------------------------------ */
+/* Sanguino support (and other 40pin DIP cpus) */
+#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega32__)
+/*------------------------------------------------------------------------ */
+/* Onboard LED is connected to pin PB0 on Sanguino */
+#if !defined(LED)
+#define LED D7 //Moteino MEGA D15
+#endif
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT PORTD
+#define UART_PIN PIND
+#define UART_DDR DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/*------------------------------------------------------------------------ */
+/* Mega support */
+#if defined(__AVR_ATmega1280__)
+/*------------------------------------------------------------------------ */
+/* Onboard LED is connected to pin PB7 on Arduino Mega */
+#if !defined(LED)
+#define LED B7
+#endif
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT PORTE
+#define UART_PIN PINE
+#define UART_DDR DDRE
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/*
+ * ------------------------------------------------------------------------
+ * A bunch of macros to enable the LED to be specifed as "B5" for bit 5
+ * of port B, and similar.
+ */
+
+#define A0 0x100
+#define A1 0x101
+#define A2 0x102
+#define A3 0x103
+#define A4 0x104
+#define A5 0x105
+#define A6 0x106
+#define A7 0x107
+
+#define B0 0x200
+#define B1 0x201
+#define B2 0x202
+#define B3 0x203
+#define B4 0x204
+#define B5 0x205
+#define B6 0x206
+#define B7 0x207
+
+#define C0 0x300
+#define C1 0x301
+#define C2 0x302
+#define C3 0x303
+#define C4 0x304
+#define C5 0x305
+#define C6 0x306
+#define C7 0x307
+
+#define D0 0x400
+#define D1 0x401
+#define D2 0x402
+#define D3 0x403
+#define D4 0x404
+#define D5 0x405
+#define D6 0x406
+#define D7 0x407
+
+#define E0 0x500
+#define E1 0x501
+#define E2 0x502
+#define E3 0x503
+#define E4 0x504
+#define E5 0x505
+#define E6 0x506
+#define E7 0x507
+
+#define F0 0x600
+#define F1 0x601
+#define F2 0x602
+#define F3 0x603
+#define F4 0x604
+#define F5 0x605
+#define F6 0x606
+#define F7 0x607
+
+#define G0 0x700
+#define G1 0x701
+#define G2 0x702
+#define G3 0x703
+#define G4 0x704
+#define G5 0x705
+#define G6 0x706
+#define G7 0x707
+
+#define H0 0x800
+#define H1 0x801
+#define H2 0x802
+#define H3 0x803
+#define H4 0x804
+#define H5 0x805
+#define H6 0x806
+#define H7 0x807
+
+#define J0 0xA00
+#define J1 0xA01
+#define J2 0xA02
+#define J3 0xA03
+#define J4 0xA04
+#define J5 0xA05
+#define J6 0xA06
+#define J7 0xA07
+
+#define K0 0xB00
+#define K1 0xB01
+#define K2 0xB02
+#define K3 0xB03
+#define K4 0xB04
+#define K5 0xB05
+#define K6 0xB06
+#define K7 0xB07
+
+#define L0 0xC00
+#define L1 0xC01
+#define L2 0xC02
+#define L3 0xC03
+#define L4 0xC04
+#define L5 0xC05
+#define L6 0xC06
+#define L7 0xC07
+
+
+
+#if LED == B0
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB0
+#elif LED == B1
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB1
+#elif LED == B2
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB2
+#elif LED == B3
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB3
+#elif LED == B4
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB4
+#elif LED == B5
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB5
+#elif LED == B6
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB6
+#elif LED == B7
+#undef LED
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB7
+
+#elif LED == C0
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC0
+#elif LED == C1
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC1
+#elif LED == C2
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC2
+#elif LED == C3
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC3
+#elif LED == C4
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC4
+#elif LED == C5
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC5
+#elif LED == C6
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC6
+#elif LED == C7
+#undef LED
+#define LED_DDR DDRC
+#define LED_PORT PORTC
+#define LED_PIN PINC
+#define LED PINC7
+
+#elif LED == D0
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND0
+#elif LED == D1
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND1
+#elif LED == D2
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND2
+#elif LED == D3
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND3
+#elif LED == D4
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND4
+#elif LED == D5
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND5
+#elif LED == D6
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND6
+#elif LED == D7
+#undef LED
+#define LED_DDR DDRD
+#define LED_PORT PORTD
+#define LED_PIN PIND
+#define LED PIND7
+
+#elif LED == E0
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE0
+#elif LED == E1
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE1
+#elif LED == E2
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE2
+#elif LED == E3
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE3
+#elif LED == E4
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE4
+#elif LED == E5
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE5
+#elif LED == E6
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE6
+#elif LED == E7
+#undef LED
+#define LED_DDR DDRE
+#define LED_PORT PORTE
+#define LED_PIN PINE
+#define LED PINE7
+
+#elif LED == F0
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF0
+#elif LED == F1
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF1
+#elif LED == F2
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF2
+#elif LED == F3
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF3
+#elif LED == F4
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF4
+#elif LED == F5
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF5
+#elif LED == F6
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF6
+#elif LED == F7
+#undef LED
+#define LED_DDR DDRF
+#define LED_PORT PORTF
+#define LED_PIN PINF
+#define LED PINF7
+
+#elif LED == G0
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING0
+#elif LED == G1
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING1
+#elif LED == G2
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING2
+#elif LED == G3
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING3
+#elif LED == G4
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING4
+#elif LED == G5
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING5
+#elif LED == G6
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING6
+#elif LED == G7
+#undef LED
+#define LED_DDR DDRG
+#define LED_PORT PORTG
+#define LED_PIN PING
+#define LED PING7
+
+#elif LED == H0
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH0
+#elif LED == H1
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH1
+#elif LED == H2
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH2
+#elif LED == H3
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH3
+#elif LED == H4
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH4
+#elif LED == H5
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH5
+#elif LED == H6
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH6
+#elif LED == H7
+#undef LED
+#define LED_DDR DDRH
+#define LED_PORT PORTH
+#define LED_PIN PINH
+#define LED PINH7
+
+#elif LED == J0
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ0
+#elif LED == J1
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ1
+#elif LED == J2
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ2
+#elif LED == J3
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ3
+#elif LED == J4
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ4
+#elif LED == J5
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ5
+#elif LED == J6
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ6
+#elif LED == J7
+#undef LED
+#define LED_DDR DDRJ
+#define LED_PORT PORTJ
+#define LED_PIN PINJ
+#define LED PINJ7
+
+#elif LED == K0
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK0
+#elif LED == K1
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK1
+#elif LED == K2
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK2
+#elif LED == K3
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK3
+#elif LED == K4
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK4
+#elif LED == K5
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK5
+#elif LED == K6
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK6
+#elif LED == K7
+#undef LED
+#define LED_DDR DDRK
+#define LED_PORT PORTK
+#define LED_PIN PINK
+#define LED PINK7
+
+#elif LED == L0
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL0
+#elif LED == L1
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL1
+#elif LED == L2
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL2
+#elif LED == L3
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL3
+#elif LED == L4
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL4
+#elif LED == L5
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL5
+#elif LED == L6
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL6
+#elif LED == L7
+#undef LED
+#define LED_DDR DDRL
+#define LED_PORT PORTL
+#define LED_PIN PINL
+#define LED PINL7
+
+#elif LED == A0
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA0
+#elif LED == A1
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA1
+#elif LED == A2
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA2
+#elif LED == A3
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA3
+#elif LED == A4
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA4
+#elif LED == A5
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA5
+#elif LED == A6
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA6
+#elif LED == A7
+#undef LED
+#define LED_DDR DDRA
+#define LED_PORT PORTA
+#define LED_PIN PINA
+#define LED PINA7
+
+#else
+#error -------------------------------------------
+#error Unrecognized LED name. Should be like "B5"
+#error -------------------------------------------
+#endif
diff --git a/hardware/MySensors/avr/bootloaders/DualOptiboot/stk500.h b/hardware/MySensors/avr/bootloaders/DualOptiboot/stk500.h
new file mode 100644
index 0000000..ca0dd91
--- /dev/null
+++ b/hardware/MySensors/avr/bootloaders/DualOptiboot/stk500.h
@@ -0,0 +1,39 @@
+/* STK500 constants list, from AVRDUDE */
+#define STK_OK 0x10
+#define STK_FAILED 0x11 // Not used
+#define STK_UNKNOWN 0x12 // Not used
+#define STK_NODEVICE 0x13 // Not used
+#define STK_INSYNC 0x14 // ' '
+#define STK_NOSYNC 0x15 // Not used
+#define ADC_CHANNEL_ERROR 0x16 // Not used
+#define ADC_MEASURE_OK 0x17 // Not used
+#define PWM_CHANNEL_ERROR 0x18 // Not used
+#define PWM_ADJUST_OK 0x19 // Not used
+#define CRC_EOP 0x20 // 'SPACE'
+#define STK_GET_SYNC 0x30 // '0'
+#define STK_GET_SIGN_ON 0x31 // '1'
+#define STK_SET_PARAMETER 0x40 // '@'
+#define STK_GET_PARAMETER 0x41 // 'A'
+#define STK_SET_DEVICE 0x42 // 'B'
+#define STK_SET_DEVICE_EXT 0x45 // 'E'
+#define STK_ENTER_PROGMODE 0x50 // 'P'
+#define STK_LEAVE_PROGMODE 0x51 // 'Q'
+#define STK_CHIP_ERASE 0x52 // 'R'
+#define STK_CHECK_AUTOINC 0x53 // 'S'
+#define STK_LOAD_ADDRESS 0x55 // 'U'
+#define STK_UNIVERSAL 0x56 // 'V'
+#define STK_PROG_FLASH 0x60 // '`'
+#define STK_PROG_DATA 0x61 // 'a'
+#define STK_PROG_FUSE 0x62 // 'b'
+#define STK_PROG_LOCK 0x63 // 'c'
+#define STK_PROG_PAGE 0x64 // 'd'
+#define STK_PROG_FUSE_EXT 0x65 // 'e'
+#define STK_READ_FLASH 0x70 // 'p'
+#define STK_READ_DATA 0x71 // 'q'
+#define STK_READ_FUSE 0x72 // 'r'
+#define STK_READ_LOCK 0x73 // 's'
+#define STK_READ_PAGE 0x74 // 't'
+#define STK_READ_SIGN 0x75 // 'u'
+#define STK_READ_OSCCAL 0x76 // 'v'
+#define STK_READ_FUSE_EXT 0x77 // 'w'
+#define STK_READ_OSCCAL_EXT 0x78 // 'x'