picprog-1.9.1/Makefile0000644000076500007650000000345411361214071013264 0ustar jaakkome# This is Picprog, Microchip PIC programmer software for the serial # port device. # Copyright © 1997,2002,2003,2004 Jaakko Hyvätti # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # 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. # # The author may be contacted at: # # Email: Jaakko.Hyvatti@iki.fi # URL: http://www.iki.fi/hyvatti/ # Phone: +358 40 5011222 # # Please send any suggestions, bug reports, success stories etc. to the # Email address above. # Please use a reasonably recent GNU make. CXX=g++ CXXFLAGS=-O2 -Wall -W -Wwrite-strings LDFLAGS=-s OBJS=main.o picport.o hexfile.o program.o PROG=picprog all: $(PROG) testport $(PROG): $(OBJS) $(CXX) $(LDFLAGS) $(OBJS) -o $@ testport: testport.o $(CXX) $(LDFLAGS) $^ -o $@ dep: $(CXX) -M $(CXXFLAGS) *.cc > .depend clean: rm -f core $(OBJS) $(PROG) tar: chmod -R a+rX,go-w . VERSION=`expr $$PWD : '.*-\([1-9]\.[1-9]\?[0-9]\(\.[0-9]\)\?\)$$'`; \ cd ..; \ tar -czvf $(PROG)-$$VERSION.tar.gz \ $(PROG)-$$VERSION/{Makefile,COPYING,README} \ $(PROG)-$$VERSION/[a-zA-Z]*.{html,png,1,h,cc} install: all install -c -o 0 -g 0 -m 755 $(PROG) /usr/local/bin/ install -c -o 0 -g 0 -m 644 *.1 /usr/local/man/man1/ # # include a dependency file if one exists # ifeq (.depend,$(wildcard .depend)) include .depend endif picprog-1.9.1/COPYING0000644000076500007650000010451311361212714012657 0ustar jaakkome 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 . picprog-1.9.1/README0000644000076500007650000000176611361214237012514 0ustar jaakkomeThis is Picprog, a Microchip PIC microcontroller programmer software for the simple serial port device. Copyright © 1997,2002,2003,2004,2005,2006,2007,2010 Jaakko Hyvätti. It may also work for serial eeproms and such with modifications. What you need: Serial port pic programming hardware, g++ compiler, Linux kernel version 2.0.32 or 2.1.45 or later ..or Cygwin DLL version 1.5.8 or later A pic assembler, for example gpasm. Quick installation instructions: make dep make make install To program for example a pic16f84 chip: picprog --burn --device=pic16f84 --input something.hex --pic /dev/ttyS1 Includes a tool to test PC serial port: testport Full manual: see the file picprog.html in this directory or The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Remember: this is not a production quality programmer! See the data sheets from Microchip for more information about what that means. picprog-1.9.1/picprog.html0000644000076500007650000012371211361223735014164 0ustar jaakkome Jaakko Hyvätti Picprog 1.9.1 documentation

http://www.iki.fi/hyvatti/pic/picprog.html


Jaakko Hyvätti Picprog 1.9.1 documentation

2010-04-14

PIC16, PIC12 and PIC18 microcontroller programmer for Linux and Windows/Cygwin.

Translations of some version of this document: Dutch

  1. Background reading
  2. Requirements
  3. Hardware
  4. Installation
  5. Usage
  6. Burning PICs
  7. Reading PICs
  8. Exit values
  9. Internals
  10. Changes
  11. Other available programmers
  12. Available languages
  13. Other software
  14. History
  15. Copyright notice

PICmicro microcontrollers, or MCUs, are fine chips that are especially easy to program with a simple device attached to a parallel or serial port. Because of the EEPROM or Flash memory, they are also easy and fast to erase and reprogram without need for UV equipment. This makes them very popular among electronics hobbyists.

At the moment this is the second implementation of a PIC programmer for Linux that works with the very simple and cheap serial port programmers. The first one I know was made by Ralph Metzler in 1996. My programmer was originally designed for PIC16C84 and PIC16F84 chips back in 1997, and since then I have implemented other chips without access to most of them. I have tested PIC16F628, PIC16F676, PIC12F675, PIC16F88, PIC16F876A, PIC16F76, PIC18F1320 and PIC18F458. Others have used many other models. The dsPIC30 family has some code in the sources, but the support is not finished yet. Some 12 bit chips should be supported but I have not tested that support.

1. Background reading

You really should take a look at the Microchip www-pages and read the device datasheets and programming specifications there.

Maybe the best source for PIC information is the home page of PICLIST discussion group. Also historically a good collection of links and software for PIC was in David Tait's PIC links page and in GNUPIC pages. I have also documented here the software I took a look at back in 1997. I have focused into Linux support, so I have never used any DOS software mentioned.

2. Requirements

Serial port pic programming hardware
See the hardware section. This device is connected to a usual serial port of your PC, and is the same device as used with many DOS PIC burning programs.
A serial port
Having a serial port on a computer is not really that usual any more. Often a serial port is optional on computer motherboards and they do not come with 9 pin or 25 pin connector installed. USB serial port adapters can be used in Linux and Windows/Cygwin. However they offer very slow performance, as every bit transmitted needs serial control lines to be toggled on and off, and each of these operations takes milliseconds over the USB line protocol. Prepare to wait minutes to hours instead of seconds when programming with USB serial port adapter.
C++ compiler (g++)
This program is written in C++, so you need a C++ compiler to compile it. This you should already have installed on your Linux system or Windows/Cygwin system.
Linux kernel version 2.0.32 or 2.1.45 or later.
This programmer needs some functionality in Linux serial driver that as of kernel versions 2.0.32 and 2.1.45 is available in standard kernels. The programmer uses TIOCSBRK and TIOCCBRK ioctl to control the state of TxD serial port output accurately. These ioctl's are standard on BSD flavor unixes, like SunOS 4, but they may still are unimplemented on some serial drivers in Linux kernel.
Cygwin DLL version 1.5.8 or later
(For Windows installations only) Earlier Cygwin versions do not contain the necessary TIOCSBRK and TIOCCBRK ioctl functionality.
A compiler for PIC
Your assembler, or C compiler, or whatever, should produce either Intel IHX32, IHX16, or IHX8M format hex files. For assembler on Linux I recommend GNU PIC Utilities gpasm.

3. Hardware

Use a serial port programmer device with the following pinouts:
TxD
Programming voltage, pin /MCLR
RTS
Clock pulse, pin RB6
DTR (output), CTS (input)
Serial data, pin RB7
A good programmer like this is for example PIC-Programmer 2 designed by Jens Madsen. Some later chips with internal oscillator modes may need a bit more complicated designs or the reprogramming of the chips can be unreliable. See JDM-B: JDM Programmer Modification: Automatic Vcc Control or RCD programmer. I have heard that other programmers work also, for example TE20 and Olimex PG2C have been tested with Picprog.

The description below is based on old version of JDM hardware. As you can see above, there are better designs by Jens Madsen and others available, please use them instead. Note however that for example the latest Jens Madsen PCB does not support PIC16F628A that needs to have pin 10, RB4/PGM grounded. Please modify the PCB to ground this pin if your chip has PGM on pin 10.

I made a minor modification to the jdm84v23 schema and pcb mask, because I thought D4 was stressed on positive clock pulses - it short circuits the rs-232 RTS pin to GND. I added a 10k resistor between D4 and D3. But it also is not absolutely required, as the clock pulses are short and rs-232 is protected for short circuits anyway. Now I have noticed that this resistor makes the programmer less reliable, especially with later PIC chips, like PIC16F76 and PIC18 family. If you have built the hardware I previously suggested, and it does not work, please short circuit that resistor or build the new PCB from Jens Madsen site. Also you can try this patch by Matthijs Kooijman to test the levels of signals: picprog-slow-test.diff . This is for an older version of picprog, so it does not apply to current code, but you get the idea.

To support for example PIC16F628 and PIC16F88, which have a low voltage programming mode, the circuit was again modified to ground the RB3 pin 9 and the RB4 pin 10. This prevents the chip from entering the low voltage programming mode. To support for example PIC12F675, PIC16F630, and PIC16F676, pin 1 was connected to Vdd. Other jumpers need to be installed as described below.

The schemantics diagram:
jdm84ne3.png

The 300 dpi pcb mask:
jdm84pcb6.png

To support for example PIC16F876A and 16F76, which have different pinouts for programming signals, you need an adapter that connects to the external connector of the above programmer. Alternatively you could redesign the pcb layout, but maybe it is easier to just solder the adaptor. Solder the pins like this:

pcb        1 -- clk  -- 27 (RB6)      ic
connector  3 -- data -- 28 (RB7)      socket
           5 -- Vss  -- 8,19,24
           7 -- Vdd  -- 20
           9 -- Vpp  -- 1

To support for example PIC12F675, PIC16F630 and PIC16F676, which have different pinouts for programming signals but do not conflict with PIC16C84 pins, you can solder jumper wires on the above pcb. You need to connect pin 16 on the socket to clock (same as pin 12), pin 17 to data (same as pins 11 and 13), and pin 18 on the socket to Vss (same as pins 5-10). Note that pin 1 is already connected to Vdd in the above PCB mask. If this connection is missing on your older PCB, connect pin 1 to pin 14 with a wire.

Always check the correct pinouts for your chip from the datasheets also!

For support for 3.3 volt in-circuit programming, see the modified circuit by Krüpl Zsolt, Hungary. The base of the transistor is moved from +5V to +3.45V with the added 22k resistor to PIC ground.

4. Installation

Linux

There are binary packages available that have been prepared by helpful users and operating system vendors. I know of the following, but cannot offer any support for them. They might be for older versions, but even if they are, check for the 10. Changes section below if you really need a later version. Some new versions of Picprog only fix small specific bug, which may not affect you at all.

To install from source, download the picprog-1.9.1.tar.gz package, if you do not already have it.

Check your system against the requirements mentioned above.

Untar the archive and change to the source file directory. You should only have to type:

make dep
make
and the program should compile without errors or warnings. If it does not, please check that your compiler, c and c++ libraries and utilities like make are of a reasonably recent, bugfree and compatible version.

After compilation you can, as a root user, just type:

make install
to install the program and manual page to /usr/local. Or just copy the files picprog and picprog.1 manually.

Make sure that you have access to the serial port device like /dev/ttyS0 or /dev/ttyS1 with the user that you are running the program as.

Windows/Cygwin

The Linux emulator for Windows, Cygwin, allows Picprog to be compiled on Windows plattforms.

To install Cygwin, go to www.cygwin.com and follow the instructions there. In short, download setup.exe and run it. You need to install at least the Developer packages Gcc C compiler, Gcc C++ compiler, Make, and Binutils in addition to the default install.

To install Picprog on Cygwin, follow the above instructions for Linux compilation from source.

Windows 2000 and XP installations that I have tried work fine. Windows 98 installations worked sometimes, and I suppose the timing routines of Picprog do not work well on Windows 98, they even lock the computer sometimes. I suggest using Windows 2000 or later.

If you are using USB serial adapters, they show up as /dev/ttyS13 or higher numbers. Try different numbers if that does not work.

5. Usage

To get information about the usage of the program, just type the program name. These options give information about the program:
--warranty, --copyright, --help
Display warranty or copyright information or the help text with list of supported chip types.
--quiet, -q
Do not display the copyright notice.
The actual operation of the program is controlled by the options --input-hexfile and --output-hexfile. If the former is present, the program acts as a burner. If the latter is specified, the program will read the contents of the PIC device eeprom memories. Both may be specified on the same command line, in which case the chip is first programmed and then read.

6. Burning PICs

Simple instructions:
  1. Compile your program into a hex file.
  2. Insert the pic16c84 or other pic chip into the socket in the programmer, or connect the in-circuit programming cable to your device.
  3. Connect the programmer device to a serial port.
  4. If the device contains calibration information, like OSCCAL word in program memory or BG bits in configuration word in PIC12F675, it is a good idea to save these for later if this is the first time you program the chip. See next chapter for more on reading chip, but this should be enough for saving the calibration:
    picprog --output saved-cal-chip1.hex --skip-ones --pic /dev/ttyS1
    
  5. Burn the program with command:
    picprog --burn --input file.hex --pic /dev/ttyS1
    
  6. If the above command produces error output that suggests that the chip was in the code protection state, or that the chip must be completely erased before programming, retry with the following command:
    picprog --erase --burn --input file.hex --pic /dev/ttyS1
    
  7. Wait for the program to complete. Burning 8192 program locations on 14 bit devices may take 3 minutes. I know better programming algorithms would speed this up significantly, but I have not had time to fix that. PIC18 family programming algorithm is significantly faster.
The burning options are:
--erase
To be able to reprogram a PIC device that has previously been programmed into Code Protection state (for example in pic16c84 Control Word fuse bit 0x10 cleared), it is necessary to bulk erase the chip. Also some PIC devices do not automatically erase each location as they are programmed, and these devices must always be bulk erased first. It is done by adding this option to the command line. The default is not to bulk erase the chip.
--burn
Actually program the device. Without this option only the syntax of input files and command line options is checked.
--input-hexfile path, -i path
Specifies the input hex file. The file can be either in IHX32, IHX16, or IHX8M formats, the format is automatically recognized.
--cc-hexfile path, -c path
Only necessary for debugging. Outputs the same data as was read from the input hex file.
--force-calibration
Force reprogramming the OSCCAL word and BG bits in control word. Default is to read the calibration values off the chip before erasing and preserving their values. Use this option if you have accidentally erased the values on chip, and you reprogram them from your saved copy which was read off the chip before the values were lost there. In general it is a really good idea to first read the empty chip and save the file somewhere if the calibration data gets lost later, either by accident or because of some bug in Picprog.
--pic-serial-port device, -p device
The device name of the serial port the programmer is connected to. Default is /dev/ttyS0. Environment variable PIC_PORT can be also used to specify the serial port. Use /dev/ttyUSB0 in Linux or /dev/ttyS13 in Windows/Cygwin for USB serial adapters.
--device chipname, -d chipname
The chip type. Environment variable PIC_DEVICE can also be used to specify device. Currently supported by code are:
auto, pic16c84, pic16cr83, pic16cr84, pic16f83, pic16f84, pic16f84a*, pic16f87*, pic16f88*, pic16c61, pic16c62, pic16c62a, pic16c62b, pic16c63, pic16c63a, pic16c64, pic16c64a, pic16c65, pic16c65a, pic16c65b, pic16c66, pic16c66a, pic16c67, pic16cr62, pic16cr63, pic16cr64, pic16cr65, pic16c620, pic16c620a, pic16cr620a, pic16c621, pic16c621a, pic16c622, pic16c622a, pic16f627*, pic16f627a*, pic16f628*, pic16f628a*, pic16f648a*, pic16f883*, pic16f884*, pic16f886*, pic16f887*, pic16ce623, pic16ce624, pic16ce625, pic16c641, pic16c642, pic16c661, pic16c662, pic16c71, pic16c710, pic16c711, pic16c712, pic16c715, pic16c716, pic16c717, pic16c72, pic16c72a, pic16cr72, pic16c73, pic16c73a, pic16c73b, pic16c74, pic16c74a, pic16c74b, pic16c76, pic16c77, pic16f72*, pic16f73*, pic16f74*, pic16f76*, pic16f77*, pic16c432, pic16c433, pic16c781, pic16c782, pic16c745, pic16c765, pic16c770, pic16c771, pic16c773, pic16c774, pic16f870*, pic16f871*, pic16f872*, pic16f873*, pic16f873a*, pic16f874*, pic16f874a*, pic16f876*, pic16f876a*, pic16f877*, pic16f877a*, pic16f818*, pic16f819*, pic16c923, pic16c924, pic16f630*, pic16f676*, pic12f629*, pic12f675*, pic12f635*, pic12f683*, pic16f631*, pic16f636*, pic16f639*, pic16f677*, pic16f684*, pic16f685*, pic16f687*, pic16f688*, pic16f689*, pic16f690*, pic18f242*, pic18f248*, pic18f252*, pic18f258*, pic18f442*, pic18f448*, pic18f452*, pic18f458*, pic18f1220*, pic18f2220*, pic18f4220*, pic18f1320*, pic18f2320*, pic18f4320*, pic18f6520*, pic18f6620*, pic18f6720*, pic18f8520*, pic18f8620*, pic18f8720*, pic18f6585*, pic18f8585*, pic18f6680*, pic18f8680*, pic18f6525*, pic18f6621*, pic18f8525*, pic18f8621*, pic18f2439*, pic18f2539*, pic18f4439*, pic18f4539*, pic18f2331*, pic18f2431*, pic18f4331*, pic18f4431*, pic18f2221*, pic18f2321*, pic18f2410*, pic18f2423*, pic18f2420*, pic18f2450*, pic18f2455*, pic18f2458*, pic18f2480*, pic18f2510*, pic18f2515*, pic18f2523*, pic18f2520*, pic18f2525*, pic18f2550*, pic18f2553*, pic18f2580*, pic18f2585*, pic18f2610*, pic18f2620*, pic18f2680*, pic18f2682*, pic18f2685*, pic18f4221*, pic18f4321*, pic18f4410*, pic18f4423*, pic18f4420*, pic18f4450*, pic18f4455*, pic18f4458*, pic18f4480*, pic18f4510*, pic18f4515*, pic18f4523*, pic18f4520*, pic18f4525*, pic18f4550*, pic18f4553*, pic18f4580*, pic18f4585*, pic18f4610*, pic18f4620*, pic18f4680*, pic18f4682*, and pic18f4685*.
The devices marked with a star (*) can be autodetected, so they need not to be specified. If code protection is active on the chip, autodetection may not work.

I do not know if all the chips work or if any other than pic16c84, pic12f675, pic16f676, pic16f76, pic16f88, pic16f876a, pic16f628, pic18f1320, and pic18f458 work, these I have tested myself. Default is to autodetect the device by reading configuration memory location 0x2006. If no device id is present, the default is pic16c84. If reading location 0x2006 with 14 bit programming algorithm fails, the PIC18 programming algorithm is used to read configuration memory locations 0x3ffffe and 0x3fffff. To add a new supported chip type, just edit the table in file hexfile.cc.

The hex file addresses (in IHX16 format) used are the ones specified by Microchip. This example is for pic16f628:
0x0000-0x07FF
Program memory, 2048 words * 14 bits.
0x2000-0x2003
ID locations.
0x2006
Device id (not present on older chips), not present in hex file
0x2007
Control word fuses
0x2100-0x217F
Data memory, 128 bytes * 8 bits.
The addresses in IHX32 and IHX8M files are not word addresses but byte addresses. Divide those addresses by 2 and you get the same addresses as in the example above.

This example is for pic18f1320. These addresses are byte addresses. IHX32 is the only option for saving PIC18 family programs in hex files.

0x000000-0x001fff
Program memory, 8192 bytes of 8 bits, or 4096 words of 16 bits.
0x200000-0x200007
ID locations.
0x3ffffe-0x3fffff
Device id, not present in hex file
0x300000-0x30000d
Control word fuses
0xf00000-0xf000ff
Data memory, 256 bytes * 8 bits.

Before interfacing with the PIC chip, Picprog calibrates its delay loops by checking the clock speed of the CPU and whether the CPU supports the TSC feature. On Linux, /proc/cpuinfo is read. On Windows/Cygwin, /proc/cpuinfo is read and CPU clock frequency is estimated. Therefore the clock frequency displayed on Windows is not necessarily exactly the true clock frequency.

Long cables, different values on capacitors and resistors, and differences on sertial ports can cause very long signal rise and fall times. The JDM device is sensitive to that, and mostly is designed to be connected directly to computer or with very short cable. The sensitivity also depends on the PIC chip type. It may help to stretch the delays in Picprog to allow for longer signal settling times. Larger delays are needed also for the uJDM programmer device. A couple of options are available. They can be tried individually and together:

--rdtsc
Uses the CPU's TSC capability, cycle counter, to measure time delays. This is the most accurate way of measuring time, and gives you the fastest programming. If you are running as root, interrupts are disabled during the time the clock pulse is down, and this may help if the chip looses power during too long delays. However, this option may not work with all CPU's, laptops, and other variable clock rate computers.
--nordtsc
Ignores the CPU's TSC capability. Try this if the programmer does not work. This is the default setting now. It is a bit slower than --rdtsc, but works more reliably on some computers.
--slow
Slow down the bit transmit delay loops to 10 microseconds. Try this if the programmer does not work without it.
--reboot
Before programming, try to switch of the microcontroller power. This works mainly on JDM type programmers, and may help on some chips with internal clock generator that otherwise would continue running the program.
--k8048
Invert the signals on the serial port to and from the programmer hardware. This is necessary for Velleman K8048 device.
--jdm
JDM style signaling on serial port. This is the default.

Old patches to solve the timing problem were made available by Werner Almesberger: picprog-1.7-werner-almesberger.diff, and by Matthijs Kooijman: picprog-slow-test.diff.

7. Reading PICs

Simple instructions:
  1. Insert the PIC chip into the socket in the programmer, or connect the in-circuit programming cable to your device.
  2. Connect the programmer device to a serial port.
  3. Read the device with command:
    picprog --output ofile.hex --pic /dev/ttyS1
    
The reading options are:
--output-hexfile path, -o path
Specifies the output hex file. The file will be written in IHX16 format, unless otherwise specified by the --ihx8m or --ihx32 options. For PIC18 family devices, file will be written in IHX32 format.
--skip-ones
When reading the PIC device, do not consider the all-ones memory locations to be programmed, and skip them in the hex file output. For 14 bit devices, this skips the program memory locations that have hex value 0x3FFF, and for PIC18 family devices, this skips byte values 0xFF. In data memory locations that have hex value 0xFF are skipped.
--ihx32, --ihx16, --ihx8m
Select the output hex file format to be either ihx16 or ihx8m, respectively. The default is ihx32 for PIC18 family devices and ihx16 for others.
--pic-serial-port device, -p device
The device name of the serial port the programmer is connected to. Default is /dev/ttyS0.

8. Exit values

Exit values are as defined in <sysexits.h>:
EX_OK, 0
no error
EX_USAGE, 64
command line option syntax error
EX_IOERR, 74
file or serial port io error, or after-programming verification failed
EX_DATAERR, 65
input file syntax error, not in IHX8M, IHX16, or IHX32 format
EX_NOINPUT, 66
unable to find input file or file open failed
EX_UNAVAILABLE, 69
user or signal interrupted programming
EX_PROTOCOL, 76
the device is unknown to the programmer

9. Internals

Source files and their contents:
picport.cc, .h
class picport: manipulates the serial port hardware. With this class you can execute programming commands like read a word, program a word, increment address etc. Look at picport.h for details.
hexfile.cc, .h
class hexfile: contains a PIC memory image. You can load and save the contents of this class to a file, and you can program and read it from the PIC chip. Programming uses class picport.
program.cc, h
class program: just some generic option handling.
main.cc
Just the main () to parse command line and call class hexfile to do its job.

10. Changes

This document has not changed much since it was first released with the 1.0 programmer. The changes include some information about new software and more accurate links to PIC information. New options to select type of device other than pic18c84 are also present.

2003-08-10 version 1.2
With help from Taneli Kalvas changed the schemantics diagram and pcb mask to ground the RB4 pin, selecting high voltage programming on for example pic16f628.
Implemented preservation of OSCCAL and other calibration data.
Added automatic detection of devices based on location 0x2006.
Merged Bart Goossens's changes to implement PIC16F73. I hope it works.

2003-08-21 version 1.3
Autodetect more chips. Fix programming of chips with OSCCAL. Fix erasing some chips - erasing and resetting code protection is now performed the hard way: all methods are tried regardless of chip type. --erase now works also without --input-hexfile flag.

2004-01-02 version 1.4
Add option --force-calibration to program OSCCAL and BG bits. Implement programming algorithms for 16f87/16f88 and 16f87Xa. Revise some timings on programmer reset to avoid operating voltage to dip. More verbose output on how many locations actually were burned.

2004-03-02 version 1.5
Fix PIC16F87xA configuration word burning. Remove the 10k resistor added by me from the PCB and schema. Add support for PIC18 family. Make the DTR be held low as long as possible. This may improve the reliability and limit stress on RS-232 port.

2004-03-19 version 1.6
Now compiles on Windows with Cygwin DLL version 1.5.8 and later. More accurate timings result in shorter programming times compared to previous versions. These timings use the CPU RDTSC instruction on x86 and AMD64 plattforms. PIC16F87/88 second configuration word programming implemented.

2004-04-28 version 1.7
Fixed 16c OTP and UV erased parts EPROM programming to use 100µs programming/overprogramming pulses. Use real time priorities and nanosleep() for delays if run under root priviledges. Relax timings so that they work out of the box with longer cables. Fixed PIC12F629 / PIC12F675 / PIC16F627a / PIC16F628a / PIC16F648a / PIC16F630 / PIC16F676 programming with >1.3GHz i386 CPU.

2006-03-05 version 1.8
Experimental dsPIC support, never tested, just compiled. Disabled the real time priorities, the nanosleep function does not work any more in Linux 2.6 kernels as it used to. Exit value 76 added to indicate unsupported chip id. Added more PIC18F models, thanks to Jan Wagemakers from Belgium.

2006-03-26 version 1.8.1
Fix a mistake with 18f[24]5[128]5 and 18f[24]6[128]0. Thanks to Jan Wagemakers for the fix.

2006-09-28 version 1.8.3
Added --rdtsc, --nordtsc and --slow options. They may help with laptops and new faster models of CPUs. Made --nordtsc the default. This was originally release 1.8.2 that did not have that default.

2008-06-05 version 1.9.0
New chips defined, including 12 bit parts, thanks to Renato Caldas, Kevin Buettner, Alexander Zangerl and Jan Wagemakers. Chip presence is no more detected with start/stop bit checking, as some chips do not clear them (see Debian bug #412778). Microcontroller is now powered off before any operations with --reboot option, thank you for the idea to Mauro Giachero. Some code changes remove duplicate port initialization. Timings have been changed completely, hopefully this fixes the erratic behaviour with some chips. Thank you for testing and ideas to Mauro Giachero and Jan Wagemakers. Added environment variables PIC_PORT and PIC_DEVICE, thanks to monttyle. Added --k8048 option for Velleman K8048 with reversed signals, thanks to Bob Dunlop and Neil Turton.

2010-04-14 version 1.9.1
Fixed a bug that prevented erasing chip with OSCCAL words. Thank you for Eckhard Neber for finding this. Read also short hexfile data lines, thanks to Jacques Klei, Salie Adams, Redzinalds Knipsis and Jani Turkia for pointing this out. Charge capacitors a little longer, suggested by Bernard Hatt. Added some NOP commands to PIC18F programming sequence, suggested by Marco Mattila. Fixed warnings with current compilers. Changed license to GPL3. Thanks to Mario Castelán Castro for reminding about that.

11. Other available programmers

PiKdev
PiKdev is a simple graphic IDE for the development of PIC-based applications. PiKdev is developed in C++ under Linux and is based on the KDE environment. It includes a programming engine which allows programming various flavors of PIC microcontrollers via classic (ie: D. Tait or JDM compatible) programming hardware connected to the parallel port or to the serial port.
PP06
Linux and Windows programming software that knows about 83 pic's and 6 programmers.
XWisp
Programmer software written in Python by Wouter van Ooijen.
serp-0.5 (serp-0.5.tgz)
A serial port programmer software for Linux, written in c++, author Ralph Metzler. It directly handles the serial hardware, standard 16450/16550 compatible uarts, and needs root priviledges for that. Unmaintained since 1996.
jdm84v23 (jdm84v23.zip, pgm84v23.zip)
A serial port programmer, schema (gif) and DOS software. The hardware manages with rs-232 interfaces with low voltage output, even as low as ±7V is fine. This is the programmer I use with linux with my own software.

I modified the circuit to include connections to pins that are needed for programming some PIC microcontrollers.

There is a new version of the PCB available on Jens Madsen site. It supports more chips without jumper wires: PIC-Programmer 2.

uJDM
A serial port programmer, stripped down version of the JDM device. Works with Picprog but needs option --slow and possibly needs even more patching for other added delays. See picprog-1.7-werner-almesberger.diff for some advice.
pip-02/com84 (pip-02.zip)
A serial port programmer, schema (gif) and DOS software. Needs +12V rs-232 positive voltage level.
prog84-3
A parallel and serial port programmer, and software for Linux and dos, written by Wim Lewis and Frank Damgaard. There is some experimental code for an USB parallel port device.
dvtait84, pic84faq (dvtait84.zip, pic84faq.zip)
A parallel port programmer, schema (ascii) and DOS software with basic and turbo-C sources included. Author David Tait. He has a lot more stuff, and some new designs to program other PICs in his links page.
mjcox84 (mjcox84.zip)
A parallel port programmer, no schema, written in assembler for DOS with 486/33 timings. Very limited. Author: Mark J Cox, m.j.cox@bradford.ac.uk.
ngoodw84 (ngoodw84.zip)
A parallel port programmer and disassembler, no schema, seems to use pins DATA1 = data and DATA2 = clock and needs external programming voltage. From Everyday Practical Electronics, February 1996, author Derren Crome. Disassembler by Nigel Goodwin nigelg@lpilsley.demon.co.uk.
Minimized PIC16C84 Programmer
Parallel port programmer, DOS software, needs external 13V power source. Author Stephen M. Nolan.

12. Available languages

Free compilers

GNU PIC Utilities
gputils have assembler, linker, disassembler and library utilities much like MPASM. They support all PICs.
SDCC - Small Device C Compiler
SDCC is a retargettable, optimizing ANSI - C compiler.
Yappa
A graphical development environment for PIC16F84 by Mark Colclough at the University of Birmingham. Yappa combines into a single application the editor, assembler and programmer interface that are needed to program a PIC. Picprog is used as the programmer backend.
picasm112b (picasm112b.tar.gz)
Assembler in ANSI-C by Timo Rossi. Outputs both IHX16 and IHX8M. You can also find disassemblers for 12 bit and 14 bit PIC's on Timo's site.
asm_c84 (asm_c84.zip)
Assembler in ANSI-C by James Cleverdon, jamesc@sequent.com. No INCLUDE, no IF, outputs IHX8M. The manual.
SIL
I have heard of free SIL language (something like Pascal/M2) compiler for PIC.
JAL
Just Another Language, a Pascal like high level language. "... I wanted a HLL which is better mached to the PIC architecture, to my programming habits, and which I could explain to the kids of the local electronics club without giving a full course on computer architecture."

Commercial demos

HI-TECH Software C compiler
A demo is available of their compiler.
elabtronics CoreChart
CoreChart (formerly named bitset) is an icon-based development tool. 30-day trial available.

13. Other software

GPSIM
PIC simulator.

14. History

Picprog was first written and released in May 1997. Around that time I briefly experimented with microcontrollers. I found no Linux software for the cheap serial programmer hardware by Jens Madsen, and I wanted to use that one as it was so simple to build. Only later did I learn about serp-0.5. Anyway, that one directly programmed PC style serial port hardware while I wanted to use standard UNIX methods of accessing serial ports. Linux was missing an IOCTL to force BREAK condition (steady +12V) on the serial data transmit line. This kind of functionality existed for example in Solaris. No problem, I created a patch for Linux kernel versions 2.0.30 and 2.1.42, submitted it, and it was included in mainline kernel versions 2.0.32 and 2.1.45.

Since the time I first wrote the software I did not work with microcontrollers at all for years, though I maintained Picprog by fixing obvious compilation problems and updating documentation. Version 1.0.1 was put together in May 2001 and included mainly documentation fixes. In June 1997 I had worked on adding support for different memory sizes of different PIC chips, and these changes and again documentation updates were released as version 1.1 in February 2002. I also found the programmer hardware I thought I lost a few years back, and was able test that it still works.

Picprog-1.0 was ported to FreeBSD and included in the distribution around September 1999. MIT MASLab 6.186, a student-run robotics course, seems to have used it since January 2001. Recently this documentation page has attracted steadily over 1000 visits per month, so I guess someone is finding it useful.

Nowadays I mostly test Picprog with new chips, and sometimes I start a new project like KanSat satellite or 8-PIN PONG, and never finish them..

15. Copyright notice

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ .

The author may be contacted at:

Email: Jaakko.Hyvatti@iki.fi
URL: http://www.iki.fi/hyvatti/

Please send any suggestions, bug reports, success stories etc. to the Email address above. To avoid my spam filters, please put the word 'picprog' somewhere on the subject line.

If you want to support the developement of picprog, please make a donation to via PayPal (click on the button).


Best viewed with any
browser
Jaakko Hyvätti/Jaakko.Hyvatti@iki.fi/+358 40 5011222
picprog-1.9.1/anybrowser3.png0000644000076500007650000000156507720425101014613 0ustar jaakkomePNG  IHDRXT`PLTEff33̙fffff3333"wwwUUUDDD"""{bKGDHIDATxՕr s@v/&fL2L|9 cs?X$r͐٘)OD X] nss&G&ͥTL^I||#^\޽"8Wع!̅z,<(@M1 R"\ٰR_葇1Bjf!=ZSVB֬!nRSQ)VVdu0 ;Cq+(> 騥R-a \ LRGWv#(|qLc"ʡ Yܬ]`3hӢyp$|ŭ},AO-$OC=clΟ^[J*  e0xO+[I`0 Oe"`%tEXtCommentclip2gif v.0.6 by Yves Piguet6s;IENDB`picprog-1.9.1/jdm84ne3.png0000644000076500007650000001063410020745744013673 0ustar jaakkomePNG  IHDRPPLTE^s,bKGDH pHYs  #utIME03Ø < IDATx] z ;^^ mzgj B0C&~ɌB Jݸqƍ7nܸqƍ7 s<=! Ǘa~Iи u ~%|̦ PW?)_)=—Sw;&|mueokvj(%d g|/F]%ӡ:j7g|cwuzV0"_, Ut}>2a{`oZ2_[&Y(ejHs^dG1vZ<_0M1i~] wƛJE C%މa2юo|wc66wR:-Mr!&{ɞ<|{\˷Ͻ-y9⁗/cg{cvĞQasljIs_`G@Sϱn5,_rAQΎGKcg Is,fAQ{4[|&iАSe:ȱ3ǚdUj)_ƾ!Z?IdG.HӠ^㦛s/*|1%K&Dm7TZ9?3x RM0>+Lu@be? |gASK;flW⥟U81`a{9H8PT33ClƠ&5u7>_'^Ys|Xsk=]T|}D_\Z S Hնj%w%A,3?|_ay&g~ N|}2D|mE^WjJs{ 8qMLU)^>oF{'3}%t`.)=}ʐ ɬF{M}>W_ʗo;gp{2ў`?o}{{?,9`OI|ӤI/ؓ.E¤'YExiғ[&=)_ m0(~ ءutEK7ؓ4.=ȊowIQ2p'Kɷ݆{/d|-?d|>wcېhs֥ܛo+o3_2쏋s\0(Iķ&CfoAT|k2hkf [feIw?: ^LΞhv\ۓks'M%Tǡ)_fkR#8q^cjíS+n|e|؞j^^)Q=uh[Au볅MX ݮ G$š!{>_\h,nj_CK3ow`r'sT]Uo)a\3p>_:-:>ͽ@9۰և]/dWҸ3bgm*|ҴE-~v|qu]Hbj?>>󥫸F5oln/j 3R}Z0rEm+hms0u  &XdNo&N+3uo?abK~gݝ@ 2("_/ vO +|qE\qI# =N:qN y|}|,`&n!jG+ũh_JY[u+ߏ|cpjVP3wATd"0a>/Mz fp-?^CDb1agٝ M)gtd|.WY''+Zw(pZ7'/D0Rgɒ7w7Ҙ GE_K+EtsP<X|KZgCX ҃l`|,>T7/oa|T|aVfNO β4b< Q˳Iχ gI=\j`O2lkU|ؓ_'53tLXT/$3=E{z|[ \{*/fۻFOϷsogOwBft8,u>ۻn6 kMϷ >>/,Gڶ7/^{$[-~&_B;uk uARWU4ߊ$=f&Kd9$as9!|9O|?g!ΘF.?jx:&]Fj0ߥo_`Ag ?Iv|Ej,ߥ/ТnI [b] N>MR9 Bzv:HF6L6amp37Jkyn_+]Xn@6u a{m+D"_džPaz/y}7R&S"V,z !_A>/o|WvaEiqyq2]Z {cQ~ZG?/w"~XA@hho3ٙ.gb joӞ9wo7aR|%7q;MT_1\ڮLsȼ7 _;VZEh ?wR _В*^[^w Luߥ2Y+G/-i̦eʩy7#곘/1SfӼS 5Rz\T]wEdoF]LLcr7C/A%~*`F+nW(_nՐ-|]&ҔEg-<M$K(ҢA6i@>gO~~`?1P,(mFWH>gޢ_W@O|P% :v!m#M_$H2g7rR%/!mDQB>۞gKifo|~,2I䑦W`U7$u( AfV7X='7Z ~;Dė`_(7ڮȿnibȭPvJQk_՛(G| V| 7.+`Ux=iQɷ*sT#M͗ͷ_fl¤n,n>7d&ue6-ɸ6jb8o=f___|;* ˊ$tf YWGy4t $]J~}S|R^\W+,kqƍ7nܘ -'IENDB`picprog-1.9.1/jdm84pcb6.png0000644000076500007650000001026310020772546014036 0ustar jaakkomePNG  IHDR|w,bKGD#2 pHYs  d_tIME-:MpDIDATxv& -^j91$ܴ'B]7 44 40F?h` 40@h` 40>š $"@h` 40@h` 2 /?;wqYq 9 vp`poA~Ct@@ [o 8 jQys?n;+P2;GYPͿECPTj%+D^FEѥx {CkW!(E E |NH`w  08*9[i7~2P)>ZQ`D׫:d|"u(Y "aqć?(HװFuo*af?YLv wTwf4/H#Mn>zwrv$ S"ָZ-q%?*u[ė . [ؐkի)u0gG7撘O~o*nּY;10eVԺ[g{Tmf -QĐS(d0$n|!0IϺ96B:<:`Q@ol}酲gzCL5[6?@V7 ^A8Ȧȗ Hbrql_>@<]]!pJ1`}ݲ^R+v_dyXC@x]_jlNv}{BO2iG/ LGm]MOۣhzLB9it2oyQ$` /lC@x' CӋP[kyAbItgض~!`'@  ~Ig9 zdʡ+$A!WAlH@d'xOhS4SG G" @{"0|[M²;)zh{!h{!h;wfj8gKwFw 8|C<&Hc΋K4&!r{oJ&:'o*\'xNؓStwhϦ'T"/e^ h[^~t._y E-@8htG_/ p]䄀qQF|j[6@;:z kUYo0AroHnL @0+8 l  Gw}Wi8_-3JrwXyutm2 4UGJ]r>*]~5 h*Q>ړܙh*1zi5Ɓ㗃"EX\wx 9qQX|jO8;1הJ7βrЬOާ,9+|@0AxrBqBrѣ.& ˖ԾfʅB&};]7M ~UVIW9a7Jr  0ZF;DX9āw;1@``Ůƀ_!a K9]n-$\rFUj ]b7!TD`}㗪ĵezHpZpJ- ` p<\$S1 $wC8g!ƀ!g@³.kӟώFg8YCxvruqdexvi> <;NQ@{T֌B"0P ` [62c'w);F`Cݱ;-~k#1ln߬B`Lw|o '\< |;DF0PC@x>9O㫳۔_|W.rM^+YSwf$zd,%@M  u臠;\O:r *8K uZH@xA XS' TC.@@޹R$` pׇ}UC@O2|R#@Oo^^Jb[!sM* x+lg/"AoEF[m"Gi;"0dH0:xf˨,Q&vh ]}^pGb 0#U;/v$vk>{)^#uȹ'K Huxg$!'u$*Q dw0TnW:oŭD|V,jg5]GcRmI-D Gcwr˵ D`8WX;N*e, UЌ`=;,v;3wc:kte+;sA<+X $` X#H ,uɾ׿-L2ݱÖqzf$>O,b`-!F`icXw<8 [ݱYv XI/'u2@V'QQ\gNtX!;ZL Df ;Va $W,w 2 Y F,gdB@;6Ie;2c P 1(TCq:xk2үr̲}tXR09L<;Je'\!-Vsctνu0Jkޫ&X;Ez*',Y+#&DcY ZvA TzǷkEFw(P|-h_˚IjCF~55sԆ^;_XT4NQzVsJN#i,Vs4kghQ pʓާ bheh3ZT!`.p \0 `.p \0 `.p \0 䀇IENDB`picprog-1.9.1/picprog.10000644000076500007650000000161310716121664013354 0ustar jaakkome.\" Copyright \[co] 2007 Jaakko Hyv\[:a]tti .TH PICPROG 1 "picprog 1.9" "29 Oct 2007" .SH NAME picprog \- Microchip PIC programmer for the serial port device .SH SYNOPSIS .B picprog .B \-\-quiet .B \-\-warranty .B \-\-copying .B \-\-help .B \-\-device .I chiptype .B \-d .I chiptype .B \-\-pic\-serial\-port .I device .B \-p .I device .B \-\-input\-hexfile .I path .B \-i .I path .B \-\-output\-hexfile .I path .B \-o .I path .B \-\-ihx32 .B \-\-ihx16 .B \-\-ihx8m .B \-\-cc\-hexfile .I path .B \-c .I path .B \-\-skip\-ones .B \-\-erase .B \-\-burn .B \-\-force\-calibration .B \-\-nordtsc .B \-\-rdtsc .B \-\-slow .B \-\-reboot .B \-q \-h \-? .SH ENVIRONMENT .B PIC_DEVICE .B PIC_PORT .SH DESCRIPTION See . .SH OPTIONS See . .SH AUTHOR Jaakko Hyv\[:a]tti .LP Jaakko.Hyvatti@iki.fi, http://www.iki.fi/hyvatti/ picprog-1.9.1/hexfile.h0000644000076500007650000001031611361213314013413 0ustar jaakkome/* -*- c++ -*- This is Picprog, Microchip PIC programmer software for the serial port device. Copyright © 1997,2002,2003,2004,2006,2008,2010 Jaakko Hyvätti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ /* Hexfile follows the Microchip hex file format for pic16c84: - program memory at locations 0-0x3ff - id at locations 0x2000-0x2003 - fuses at location 0x2007 - data memory at locations 0x2100-0x213f */ #ifndef H_HEXFILE #define H_HEXFILE #include using namespace std; #include "picport.h" class hexfile { // pic16 family: program size is counted in words. // pic18 family: program memory size is counted in bytes. short *pgm; short *data; short conf [16]; short ids [8]; // Return code used in program_location () to indicate that the // location already was programmed to specified value. static const int NOT_PROGRAMMED = -3; void reset_code_protection (picport& pic); int program_location (picport& pic, unsigned long addr, short word, bool isdata) const; bool verify18 (picport& pic, const short *pgmp, unsigned long addr, unsigned long len, unsigned long panel_size, bool verbose) const; int program18 (picport& pic, const short *pgmp, unsigned long addr, unsigned long len, unsigned long panel_size) const; public: enum formats { unknown, ihx8m, ihx16, ihx32 }; enum memtypes { flash, flash2, flash3, flash4, flash5, flash18, flash30, eeprom, eprom, eprom18, prom, rom}; private: int dev; int addr_max; // Used in inc_addr command for 12f only void save_line (ofstream& f, const short *pgmp, unsigned long begin, unsigned long len, enum formats format) const; int save_region (ofstream& f, const short *pgmp, unsigned long addr0, unsigned long len0, enum formats format, bool skip_ones, unsigned long &addr32) const; int read_code (picport &pic, short *pgmp, unsigned long addr, unsigned long len); struct devinf { const char *name; unsigned long prog_size; // How many words are reserved at the end of program memory // for for example oscillator calibration? unsigned long prog_preserved; // Bits that must be preserved of configuration word 0x2007. int config_mask; unsigned conf_size; // Either 12 or 14 for now. Only 14 bit devices tested int prog_bits; // Original 18f parts used multipanel writes. 0 disables this. int panel_size; // How many bytes/words to write at one programming command (18f). // 0 means unknown for 14 bit series, 1 byte writes work. // In the future maybe for 14 bit series multiword programming // will also be implemented. In that case, fill this field // for them too. int write_size; enum memtypes prog_type; unsigned data_size; enum memtypes data_type; // Device id stored at 0x2006. -1==no id on this device. int device_id; }; static const struct devinf deviceinfo []; public: hexfile () : pgm(0), data(0), dev(-1), addr_max(0) {}; ~hexfile () { if (pgm) delete [] pgm; if (data) delete [] data; } int setdevice (picport &pic, int& d); int load (const char *name); int save (const char *name, enum formats format, bool skip_ones) const; int program (picport &pic, bool erase, bool nopreserve); int read (picport &pic); // statics static int find_device (const char *name); static void print_devices (); }; #endif // H_HEXFILE picprog-1.9.1/picport.h0000644000076500007650000000606611361213274013463 0ustar jaakkome/* -*- c++ -*- This is Picprog, Microchip PIC programmer software for the serial port device. Copyright © 1997,2002,2003,2004,2008,2010 Jaakko Hyvätti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #ifndef H_PICPORT #define H_PICPORT #include #include #include class picport { public: enum hardware_types { jdm, k8048 }; private: int fd; struct termios saved, termstate; unsigned long addr; int debug_on; enum hardware_types hardware; char *portname; int W[16]; int modembits; void set_clock_data (int rts, int dtr); void set_vpp (int vpp); void p_out (int b); int p_in (); #if defined(__x86_64__) || defined(__i386__) #define RDTSC_WORKS #endif // How many tsc clocks (cpu clock cycles) per 1000 ns static unsigned int tsc_1000ns; static int cable_delay; static int use_nanosleep; public: static void delay (long ns); enum commands { load_conf = 0, data_for_prog = 2, data_from_prog = 4, inc_addr = 6, beg_prog = 010, data_for_data = 3, data_from_data = 5, erase_prog = 011, erase_data = 013, command1 = 1, command7 = 7, end_prog = 016, end_prog_only = 027, beg_prog_only = 030, chip_erase = 037 }; enum commands18 { instr = 000, shift_out = 002, tread = 010, tread_inc = 011, tread_dec = 012, inc_tread = 013, twrite = 014, twrite_inc2 = 015, twrite_dec2 = 016, twrite_prog = 017, // flag for command18() method to implement programming delay by // holding fourth command clock cycle up. nop_prog = 0100, // Flag for erase delay nop_erase = 0200, }; enum commands30 { SIX = 0, REGOUT = 1, }; picport (const char *tty, bool nordtsc, bool slow, bool reboot, enum hardware_types h); ~picport (); int command (enum commands comm, int data = 0); int command18 (enum commands18 comm, int data = 0); int command30 (enum commands30 comm, int data = 0); void setaddress (unsigned long a); void setaddress30 (unsigned long a); unsigned long address () { return addr; } void force (); void reset (unsigned long reset_address); const char *port () { return portname; } void debug (int d) { debug_on = d; } }; #endif // H_PICPORT picprog-1.9.1/program.h0000644000076500007650000000255511361213250013443 0ustar jaakkome/* -*- c++ -*- This is a generic program misc functions class v1.0. Copyright 1997,2002,2003,2004,2010 Jaakko Hyvtti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #ifndef H_PROGRAM #define H_PROGRAM #include class program { static const char warranty_t []; static const char copying_t []; public: char *name; program (); ~program (); void init (char *argv []); void warranty (); void copying (); void usage (struct option *long_opts, char *short_opts); }; #endif // H_PROGRAM picprog-1.9.1/hexfile.cc0000644000076500007650000021402311361213467013563 0ustar jaakkome/* -*- c++ -*- This is Picprog, Microchip PIC programmer software for the serial port device. Copyright © 1997,2002,2003,2004,2006,2008,2010 Jaakko Hyvätti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #include #include #include #include #include #include #include #include #include #include #include "hexfile.h" using namespace std; /* The exact programmable memory type, prom/eprom/eeprom/flash, does not affect the operations of the program. Therefore I have not checked if every chip has the correct type specified. If rom type is specified, this program only reads the memory and does not atempt to burn it. Structure fields: - Name, used in command line option to select the device. - Program memory size in words. - Number of preserved words at the end of program memory, for example oscillator calibration word. I have not checked all datasheets for which devices have one, only some. Please check the datasheet before you overwrite these configuration words! As a precaution, please read them first off the chip and write down somewhere! - configuration word preserved bits mask - number of configuration words. 1 for 14 bit devices, 14 for PIC18 and 2 for 16f87 and 16f88. - Word bit length. Only 14 bit and 16 bit (18f) ones supported. - For 18f series, panel size. 0 means multipanel writes disabled. - How many words or bytes to write at one command (18f) - Program memory type. - Non-volatile data memory size. - Non-volatile data memory type. - location 0x2006 or 0x3ffffe device id (-1 == device has no known id) */ const struct hexfile::devinf hexfile::deviceinfo [] = { // 16x8x family {"pic16c84", 1024, 0, 0, 1, 14, 0, 0, eeprom, 64, eeprom, -1}, // no OSCCAL {"pic16cr83", 512, 0, 0, 1, 14, 0, 0, rom, 64, eeprom, -1}, {"pic16cr84", 1024, 0, 0, 1, 14, 0, 0, rom, 64, eeprom, -1}, {"pic16f83", 512, 0, 0, 1, 14, 0, 0, flash, 64, eeprom, -1}, {"pic16f84", 1024, 0, 0, 1, 14, 0, 0, flash, 64, eeprom, -1}, // no OSCCAL {"pic16f84a", 1024, 0, 0, 1, 14, 0, 0, flash, 64, eeprom, 0x0560}, {"pic16f87", 4096, 0, 0, 2, 14, 0, 0, flash5, 256, eeprom, 0x0720}, {"pic16f88", 4096, 0, 0, 2, 14, 0, 0, flash5, 256, eeprom, 0x0760}, // 16c6x family {"pic16c61", 1024, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, // ? {"pic16c62", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c62a", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c62b", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c63", 4096, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c63a", 4096, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c64", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c64a", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c65", 4096, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c65a", 4096, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c65b", 4096, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c66", 8192, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c66a", 8192, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c67", 8192, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16cr62", 2048, 0, 0, 1, 14, 0, 0, rom, 0, rom, -1}, {"pic16cr63", 4096, 0, 0, 1, 14, 0, 0, rom, 0, rom, -1}, {"pic16cr64", 2048, 0, 0, 1, 14, 0, 0, rom, 0, rom, -1}, {"pic16cr65", 4096, 0, 0, 1, 14, 0, 0, rom, 0, rom, -1}, // 16c62x family {"pic16c620", 512, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c620a", 512, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16cr620a", 512, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c621", 1024, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c621a", 1024, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c622", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c622a", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16f627", 1024, 0, 0, 1, 14, 0, 0, flash, 128, eeprom, 0x07a0}, // no OSCCAL {"pic16f627a", 1024, 0, 0, 1, 14, 0, 0, flash4, 128, eeprom, 0x1040}, // no OSCCAL {"pic16f628", 2048, 0, 0, 1, 14, 0, 0, flash, 128, eeprom, 0x07c0}, // no OSCCAL {"pic16f628a", 2048, 0, 0, 1, 14, 0, 0, flash4, 128, eeprom, 0x1060}, // no OSCCAL {"pic16f648a", 4096, 0, 0, 1, 14, 0, 0, flash4, 128, eeprom, 0x1100}, // no OSCCAL // 16f88x family {"pic16f883", 4096, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x2020}, {"pic16f884", 4096, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x2040}, {"pic16f886", 8192, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x2060}, {"pic16f887", 8192, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x2080}, // 16ce62x family {"pic16ce623", 512, 0, 0, 1, 14, 0, 0, eprom, 128, eeprom, -1}, {"pic16ce624", 1024, 0, 0, 1, 14, 0, 0, eprom, 128, eeprom, -1}, {"pic16ce625", 2048, 0, 0, 1, 14, 0, 0, eprom, 128, eeprom, -1}, // 16c64x, 16c66x families {"pic16c641", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c642", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c661", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c662", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, // 16c7x, 16c77x families {"pic16c71", 1024, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c710", 512, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c711", 1024, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c712", 1024, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c715", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c716", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c717", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c72", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c72a", 2048, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16cr72", 2048, 0, 0, 1, 14, 0, 0, rom, 0, rom, -1}, {"pic16c73", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c73a", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c73b", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c74", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c74a", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c74b", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c76", 8192, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c77", 8192, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, // 16f7x family {"pic16f72", 4096, 0, 0, 1, 14, 0, 0, flash2, 0, rom, 0x00a0}, {"pic16f73", 4096, 0, 0, 1, 14, 0, 0, flash2, 0, rom, 0x0600}, {"pic16f74", 4096, 0, 0, 1, 14, 0, 0, flash2, 0, rom, 0x0620}, {"pic16f76", 8192, 0, 0, 1, 14, 0, 0, flash2, 0, rom, 0x0640}, {"pic16f77", 8192, 0, 0, 1, 14, 0, 0, flash2, 0, rom, 0x0660}, // 16f7x7 family {"pic16f737", 4096, 0, 0, 2, 14, 0, 0, flash2, 0, rom, 0x0ba0}, {"pic16f747", 4096, 0, 0, 2, 14, 0, 0, flash2, 0, rom, 0x0be0}, {"pic16f767", 8192, 0, 0, 2, 14, 0, 0, flash2, 0, rom, 0x0ea0}, {"pic16f777", 8192, 0, 0, 2, 14, 0, 0, flash2, 0, rom, 0x0de0}, // 16c43x family {"pic16c432", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c433", 2048, 1, 0, 1, 14, 0, 0, prom, 0, rom, -1}, // 16c78x family {"pic16c781", 1024, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c782", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, // 16c7x5 family {"pic16c745", 8192, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic16c765", 8192, 0, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, // 16c77x family {"pic16c770", 2048, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c771", 4096, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c773", 8192, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, {"pic16c774", 8192, 0, 0, 1, 14, 0, 0, prom, 0, rom, -1}, // 16f87x family {"pic16f870", 2048, 0, 0, 1, 14, 0, 0, flash, 64, eeprom, 0x0d00}, {"pic16f871", 2048, 0, 0, 1, 14, 0, 0, flash, 64, eeprom, 0x0d20}, {"pic16f872", 2048, 0, 0, 1, 14, 0, 0, flash, 64, eeprom, 0x08e0}, {"pic16f873", 4096, 0, 0, 1, 14, 0, 0, flash, 128, eeprom, 0x0960}, {"pic16f873a", 4096, 0, 0, 1, 14, 0, 0, flash3, 128, eeprom, 0x0e40}, {"pic16f874", 4096, 0, 0, 1, 14, 0, 0, flash, 128, eeprom, 0x0920}, {"pic16f874a", 4096, 0, 0, 1, 14, 0, 0, flash3, 128, eeprom, 0x0e60}, {"pic16f876", 8192, 0, 0, 1, 14, 0, 0, flash, 256, eeprom, 0x09e0}, {"pic16f876a", 8192, 0, 0, 1, 14, 0, 0, flash3, 256, eeprom, 0x0e00}, {"pic16f877", 8192, 0, 0, 1, 14, 0, 0, flash, 256, eeprom, 0x09a0}, {"pic16f877a", 8192, 0, 0, 1, 14, 0, 0, flash3, 256, eeprom, 0x0e20}, {"pic16f785", 2048, 0, 0, 1, 14, 0, 0, flash4, 256, eeprom, 0x1200}, {"pic16hv785", 2048, 0, 0, 1, 14, 0, 0, flash4, 256, eeprom, 0x1220}, {"pic16f818", 1024, 0, 0, 1, 14, 0, 0, flash5, 128, eeprom, 0x04c0}, {"pic16f819", 2048, 0, 0, 1, 14, 0, 0, flash5, 128, eeprom, 0x04e0}, {"pic16c923", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, eprom, -1}, {"pic16c924", 4096, 0, 0, 1, 14, 0, 0, eprom, 0, eprom, -1}, {"pic16f630", 1024, 1, 0x3000, 1, 14, 0, 0, flash4, 128, eeprom, 0x10c0}, {"pic16f676", 1024, 1, 0x3000, 1, 14, 0, 0, flash4, 128, eeprom, 0x10e0}, // 12 {"pic12c508", 512, 1, 0, 1, 12, 0, 0, eprom, 0, rom, -1}, {"pic12c508a", 512, 1, 0, 1, 12, 0, 0, eprom, 0, rom, -1}, {"pic12f508", 512, 1, 0, 1, 12, 0, 0, flash2, 0, rom, -1}, {"pic12ce518", 512, 0, 0, 1, 12, 0, 0, eprom, 16, eeprom, -1}, {"pic12c509", 1024, 1, 0, 1, 12, 0, 0, eprom, 0, rom, -1}, {"pic12c509a", 1024, 0, 0, 1, 12, 0, 0, eprom, 0, rom, -1}, {"pic12f509", 1024, 1, 0, 1, 12, 0, 0, flash2, 0, rom, -1}, {"pic12ce519", 1024, 0, 0, 1, 12, 0, 0, eprom, 16, eeprom, -1}, {"pic12cr509a",1024, 0, 0, 1, 12, 0, 0, rom, 0, rom, -1}, {"pic12c671", 1024, 1, 0, 1, 14, 0, 0, eprom, 0, rom, 0x0500}, {"pic12c672", 2048, 1, 0, 1, 14, 0, 0, eprom, 0, rom, -1}, {"pic12ce673", 1024, 1, 0, 1, 14, 0, 0, eprom, 16, eeprom, -1}, {"pic12ce674", 2048, 1, 0, 1, 14, 0, 0, eprom, 16, eeprom, -1}, {"pic16c505", 1024, 1, 0, 1, 12, 0, 0, eprom, 0, rom, -1}, {"pic12f629", 1024, 1, 0x3000, 1, 14, 0, 0, flash4, 128, eeprom, 0x0f80}, {"pic12f675", 1024, 1, 0x3000, 1, 14, 0, 0, flash4, 128, eeprom, 0x0fc0}, // pic12f635: has 2 calibration words in 2008 and 2009, no osccal // Some others below have 1 calibration word in 2008. {"pic12f635", 1024, 0, 0, 3, 14, 0, 0, flash4, 128, eeprom, 0x0fa0}, {"pic12f683", 2048, 0, 0, 3, 14, 0, 0, flash4, 256, eeprom, 0x0460}, {"pic16f631", 1024, 0, 0, 2, 14, 0, 0, flash4, 128, eeprom, 0x1420}, {"pic16f636", 2048, 0, 0, 3, 14, 0, 0, flash4, 256, eeprom, 0x10a0}, // ?? same {"pic16f639", 2048, 0, 0, 3, 14, 0, 0, flash4, 256, eeprom, 0x10a0}, // ?? same {"pic16f677", 2048, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x1440}, {"pic16f684", 2048, 0, 0, 3, 14, 0, 0, flash4, 256, eeprom, 0x1080}, {"pic16f685", 4096, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x04a0}, {"pic16f687", 2048, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x1320}, {"pic16f688", 4096, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x1180}, {"pic16f689", 4096, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x1340}, {"pic16f690", 4096, 0, 0, 2, 14, 0, 0, flash4, 256, eeprom, 0x1400}, // 18f original series // Multi-panel writes // Write Buffer Size 8 {"pic18f242", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0480}, // Same as pic18f2439 {"pic18f248", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0800}, {"pic18f252", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0400}, // Same as pic18f2539 {"pic18f258", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0840}, {"pic18f442", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x04a0}, // Same as pic18f4439 {"pic18f448", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0820}, {"pic18f452", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0420}, // Same as pic18f4539 {"pic18f458", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0860}, {"pic18f1220", 4 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x07e0}, {"pic18f2220", 4 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0580}, {"pic18f4220", 4 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x05a0}, {"pic18f1320", 8 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x07c0}, {"pic18f2320", 8 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0500}, {"pic18f4320", 8 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0520}, {"pic18f6520", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0b20}, {"pic18f6620", 64 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0660}, {"pic18f6720", 128 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0620}, {"pic18f8520", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0b00}, {"pic18f8620", 64 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0640}, {"pic18f8720", 128 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0600}, {"pic18f6585", 48 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0a60}, {"pic18f8585", 48 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0a20}, {"pic18f6680", 64 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0a40}, {"pic18f8680", 64 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0a00}, {"pic18f6525", 48 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0ae0}, {"pic18f6621", 64 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0aa0}, {"pic18f8525", 48 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0ac0}, {"pic18f8621", 64 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 1024, eeprom, 0x0a80}, {"pic18f2439", 12 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0480}, // Same as pic18f242 {"pic18f2539", 24 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0400}, // Same as pic18f252 {"pic18f4439", 12 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x04a0}, // Same as pic18f442 {"pic18f4539", 24 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0420}, // Same as pic18f452 {"pic18f2331", 8 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x08e0}, {"pic18f2431", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x08c0}, {"pic18f4331", 8 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x08a0}, {"pic18f4431", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, flash18, 256, eeprom, 0x0880}, // PIC18F2xx0/2x21/2xx5/4xx0/4x21/4xx5 // Works without Multi-panel writes --> panel_size == 0 // Write Buffer Size differs 8, 32, 64 {"pic18f2221", 4 * 1024, 0, 0, 14, 16, 0, 8, flash18, 256, eeprom, 0x2160}, {"pic18f2321", 8 * 1024, 0, 0, 14, 16, 0, 8, flash18, 256, eeprom, 0x2120}, {"pic18f2410", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 0, eeprom, 0x1160}, {"pic18f2423", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1150}, // Revision high bit == 1 {"pic18f2420", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1140}, // Must be listed after pic18f2423 {"pic18f2450", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 0, eeprom, 0x2420}, {"pic18f2455", 24 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1260}, {"pic18f2458", 24 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x2a60}, {"pic18f2480", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1ae0}, {"pic18f2510", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 0, eeprom, 0x1120}, {"pic18f2515", 48 * 1024, 0, 0, 14, 16, 0, 64, flash18, 0, eeprom, 0x0ce0}, {"pic18f2523", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1110}, // Revision high bit == 1 {"pic18f2520", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1100}, // Must be listed after pic18f2523 {"pic18f2525", 48 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0cc0}, {"pic18f2550", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1240}, {"pic18f2553", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x2a40}, {"pic18f2580", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1ac0}, {"pic18f2585", 48 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0ee0}, {"pic18f2610", 64 * 1024, 0, 0, 14, 16, 0, 64, flash18, 0, eeprom, 0x0ca0}, {"pic18f2620", 64 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0c80}, {"pic18f2680", 64 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0ec0}, {"pic18f2682", 80 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x2700}, {"pic18f2685", 96 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x2720}, {"pic18f4221", 4 * 1024, 0, 0, 14, 16, 0, 8, flash18, 256, eeprom, 0x2140}, {"pic18f4321", 8 * 1024, 0, 0, 14, 16, 0, 8, flash18, 256, eeprom, 0x2100}, {"pic18f4410", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 0, eeprom, 0x10e0}, {"pic18f4423", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x10d0}, // Revision high bit == 1 {"pic18f4420", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x10c0}, // Must be listed after pic18f4423 {"pic18f4450", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 0, eeprom, 0x2400}, {"pic18f4455", 24 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1220}, {"pic18f4458", 24 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x2a20}, {"pic18f4480", 16 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1aa0}, {"pic18f4510", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 0, eeprom, 0x10a0}, {"pic18f4515", 48 * 1024, 0, 0, 14, 16, 0, 64, flash18, 0, eeprom, 0x0c60}, {"pic18f4523", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1090}, // Revision high bit == 1 {"pic18f4520", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1080}, // Must be listed after pic18f4523 {"pic18f4525", 48 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0c40}, {"pic18f4550", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1200}, {"pic18f4553", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x2a00}, {"pic18f4580", 32 * 1024, 0, 0, 14, 16, 0, 32, flash18, 256, eeprom, 0x1a80}, {"pic18f4585", 48 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0ea0}, {"pic18f4610", 64 * 1024, 0, 0, 14, 16, 0, 64, flash18, 0, eeprom, 0x0c20}, {"pic18f4620", 64 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0c00}, {"pic18f4680", 64 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x0e80}, {"pic18f4682", 80 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x2740}, {"pic18f4685", 96 * 1024, 0, 0, 14, 16, 0, 64, flash18, 1024, eeprom, 0x2760}, // OTP parts. ID bits are listed as 0x0002 for all of these, // I do not know how to handle that. {"pic18c242", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, eprom18, 0, rom, -1}, {"pic18c252", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, eprom18, 0, rom, -1}, {"pic18c442", 16 * 1024, 0, 0, 14, 16, 8*1024, 8, eprom18, 0, rom, -1}, {"pic18c452", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, eprom18, 0, rom, -1}, {"pic18c658", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, eprom18, 0, rom, -1}, {"pic18c858", 32 * 1024, 0, 0, 14, 16, 8*1024, 8, eprom18, 0, rom, -1}, /* 18f series product pages have these chips listed, but they are not supported for now. pic18c601 No programmable memory pic18c801 pic18f6410 No information available, future products pic18f6490 pic18f8410 pic18f8490 */ // dspic - work has started. {"dspic30f2010", 4 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0040}, {"dspic30f2011", 4 * 3072, 0, 0, 16, 24, 0, 0, flash30, 0, rom, 0x00c0}, {"dspic30f2012", 4 * 3072, 0, 0, 16, 24, 0, 0, flash30, 0, rom, 0x00c2}, {"dspic30f3010", 8 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, -1 }, {"dspic30f3011", 8 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, -1 }, {"dspic30f3012", 8 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x00c1}, {"dspic30f3013", 8 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x00c3}, {"dspic30f3014", 8 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0140}, {"dspic30f4011", 16 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0101}, {"dspic30f4012", 16 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0100}, {"dspic30f4013", 16 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0141}, {"dspic30f5011", 22 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0080}, {"dspic30f5013", 22 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, 0x0081}, {"dspic30f5015", 22 * 3072, 0, 0, 16, 24, 0, 0, flash30, 1024, eeprom, -1 }, {"dspic30f6010", 48 * 3072, 0, 0, 16, 24, 0, 0, flash30, 4096, eeprom, 0x0188}, {"dspic30f6011", 44 * 3072, 0, 0, 16, 24, 0, 0, flash30, 2048, eeprom, 0x0192}, {"dspic30f6012", 48 * 3072, 0, 0, 16, 24, 0, 0, flash30, 4096, eeprom, 0x0193}, {"dspic30f6013", 44 * 3072, 0, 0, 16, 24, 0, 0, flash30, 2048, eeprom, 0x0197}, {"dspic30f6014", 48 * 3072, 0, 0, 16, 24, 0, 0, flash30, 4096, eeprom, 0x0198}, }; static int got_signal = 0; void term_handler (int a) { got_signal = 1; signal (a, term_handler); } int hexfile::load (const char *name) { ifstream f(name); char buf [128]; int line = 0; unsigned long addr32 = 0; enum formats format = unknown; unsigned long addr; int words, check, sum, word, i; int e; if (!f) { e = errno; cerr << name << ":unable to load hexfile:" << strerror (e) << endl; return EX_NOINPUT; } if (dev < 0) { cerr << "Internal error: no device defined" << endl; return EX_SOFTWARE; } while (f.get (buf, sizeof (buf))) { line++; char c; if (f.get (c) && '\n' != c) { cerr << name << ':' << line << ":long input line" << endl; return EX_DATAERR; } int len = strlen (buf); while (len && isspace (buf [len-1])) len--; buf [len] = '\0'; if (!strcmp (buf, ":00000001FF")) // eof return EX_OK; if (15 == len && (unknown == format || ihx32 == format) && !strncmp (buf, ":02000004", 9)) { // ihx32 address extension format = ihx32; check = strtol (buf + 13, 0, 16); buf [len - 2] = '\0'; addr32 = strtol (buf + 9, 0, 16); sum = 0x02 + 0x04 + addr32 + (addr32 >> 8); if ((sum + check) & 0xff) { cerr << name << ':' << line << ":checksum mismatch, checksum is 0x" << hex << setw(2) << setfill('0') << check << ", should be 0x" << setw(2) << (-sum & 0xff) << dec << endl; return EX_DATAERR; } addr32 <<= 16; continue; } if (!len) continue; // empty line, I do not want to whine about it i = len - 1; while (i && isxdigit (buf [i])) i--; if (i || ':' != buf [0] || 1 != (len & 1) || len < 13 || '0' != buf [7] || '0' != buf [8]) { cerr << name << ':' << line << ":invalid input line." << endl << "Are you sure this is an 8 or 16 bit intel hex file?" << endl; return EX_DATAERR; } check = strtol (buf + len - 2, 0, 16); buf [7] = '\0'; addr = strtol (buf + 3, 0, 16); buf [3] = '\0'; words = strtol (buf + 1, 0, 16); if (unknown == format) { if (words * 4 + 11 == len) format = ihx16; else if (words * 2 + 11 == len) format = ihx8m; else { cerr << name << ':' << line << ":unknown input format, only ihx8m, ihx16, and ihx32 accepted" << endl; return EX_DATAERR; } } if (words * (ihx16 == format ? 4 : 2) + 11 != len) { cerr << name << ':' << line << ":line length mismatch:" << (ihx16 == format ? "ihx16 " : (ihx8m == format ? "ihx8m " : "ihx32 ")) << words * (ihx16 == format ? 4 : 2) + 11 << " != " << len << endl; return EX_DATAERR; } sum = words + addr + (addr >> 8); addr += addr32; if (14 == deviceinfo [dev].prog_bits) { if (ihx16 != format) { if ((words & 1) || (addr & 1)) { cerr << name << ':' << line << ":odd address or number of words." << endl; return EX_DATAERR; } words /= 2; addr /= 2; } while (words--) { buf [13 + words * 4] = '\0'; word = strtol (buf + 9 + words * 4, 0, 16); if (ihx16 != format) word = (word & 0xff) << 8 | word >> 8; sum += word + (word >> 8); unsigned long a = addr + words; if (a >= 0x2007 && a < 0x2007 + deviceinfo [dev].conf_size) conf [a - 0x2007] = word & 0x3fff; else if (a >= 0x2100 && a < 0x2100 + deviceinfo [dev].data_size) data [a - 0x2100] = word & 0x00ff; else if (a >= 0x2000 && a < 0x2004) ids [a - 0x2000] = word & 0x3fff; else if (a < deviceinfo [dev].prog_size) pgm [a] = word & 0x3fff; else { cerr << name << ':' << line << ":invalid address 0x" << hex << setw(4) << setfill('0') << addr << dec << ", possibly not hex file for correct pic type?" << endl; return EX_DATAERR; } } } else if (12 == deviceinfo [dev].prog_bits) { if (ihx16 != format) { if ((words & 1) || (addr & 1)) { cerr << name << ':' << line << ":odd address or number of words." << endl; return EX_DATAERR; } words /= 2; addr /= 2; } while (words--) { buf [13 + words * 4] = '\0'; word = strtol (buf + 9 + words * 4, 0, 16); if (ihx16 != format) word = (word & 0xff) << 8 | word >> 8; sum += word + (word >> 8); unsigned long a = addr + words; if (a >= 0xfff && a < 0xfff + deviceinfo [dev].conf_size) conf [a - 0xfff] = word & 0xfff; else if (a >= deviceinfo [dev].prog_size && a < deviceinfo [dev].prog_size + 5) // Includes 4 id words and a backup osccal word ids [a - deviceinfo [dev].prog_size] = word & 0xfff; else if (a < deviceinfo [dev].prog_size) pgm [a] = word & 0xfff; else { cerr << name << ':' << line << ":invalid address 0x" << hex << setw(4) << setfill('0') << addr << dec << ", possibly not hex file for correct pic type?" << endl; return EX_DATAERR; } } } else { // pic18, dspic30 if (ihx16 == format) { words *= 2; addr *= 2; } while (words--) { buf [11 + words * 2] = '\0'; word = strtol (buf + 9 + words * 2, 0, 16); sum += word; unsigned long a = addr + words; if (ihx16 == format) a ^= 1; if ((flash18 == deviceinfo [dev].prog_type) && a >= 0x300000 && a < 0x300000 + deviceinfo [dev].conf_size) conf [a - 0x300000] = word; else if ((flash18 == deviceinfo [dev].prog_type) && a >= 0xf00000 && a < 0xf00000 + deviceinfo [dev].data_size) data [a - 0xf00000] = word; else if ((flash18 == deviceinfo [dev].prog_type) && a >= 0x200000 && a < 0x200008) ids [a - 0x200000] = word; else if (flash30 == deviceinfo [dev].prog_type && a >= 0xf80000 && a < 0xf80000 + deviceinfo [dev].conf_size) conf [a - 0xf80000] = word; else if (flash30 == deviceinfo [dev].prog_type && a >= 0x800000 - deviceinfo [dev].data_size && a < 0x800000) data [a - (0x800000 - deviceinfo [dev].data_size)] = word; else if (a < deviceinfo [dev].prog_size) pgm [a] = word; else { cerr << name << ':' << line << ":invalid address 0x" << hex << setw(6) << setfill('0') << a << dec << ", possibly not hex file for correct pic type?" << endl; return EX_DATAERR; } } } if ((sum + check) & 0xff) { cerr << name << ':' << line << ":checksum mismatch, checksum is 0x" << hex << setw(2) << setfill('0') << check << ", should be 0x" << setw(2) << (-sum & 0xff) << dec << endl; return EX_DATAERR; } } e = errno; if (!f.eof ()) { cerr << name << ':' << line << ':' << strerror (e) << ":" << endl; return EX_IOERR; } cerr << name << ':' << line << ":warning:unexpected eof" << endl; return EX_OK; } void hexfile::save_line (ofstream& f, const short *pgmp, unsigned long begin, unsigned long len, enum hexfile::formats format) const { unsigned long p_begin, p_len, i; int sum; // f << "#saving line " << setw(6) << begin << " len " << setw(2) << len << endl; if (14 == deviceinfo [dev].prog_bits) { if (ihx16 == format) { p_begin = begin; p_len = len; } else { p_begin = begin * 2; p_len = len * 2; } f << ':' << setw (2) << p_len << setw (4) << (p_begin & 0xffff) << "00"; sum = p_len + p_begin + (p_begin >> 8); for (i = 0; i != len; i++) { int word = pgmp [i]; if (ihx16 != format) word = (word & 0xff) << 8 | (word & 0xff00) >> 8; f << setw (4) << word; sum += word + (word >> 8); } f << setw (2) << (-sum & 0xff) << endl; } else { // pic18, dspic30 f << ':' << setw (2) << len << setw (4) << (begin & 0xffff) << "00"; sum = len + begin + (begin >> 8); for (i = 0; i != len; i++) { int word = pgmp [i]; f << setw (2) << word; sum += word; } f << setw (2) << (-sum & 0xff) << endl; } } int hexfile::save_region (ofstream& f, const short *pgmp, unsigned long addr0, unsigned long len0, enum hexfile::formats format, bool skip_ones, unsigned long &addr32) const { unsigned long len; unsigned long addr = addr0; short skip_value; unsigned long rowlen; if (!skip_ones) skip_value = -1; else if (16 <= deviceinfo [dev].prog_bits || (addr0 >= 0x2100 && addr0 < 0x2100 + deviceinfo [dev].data_size)) skip_value = 0xff; else if (12 == deviceinfo [dev].prog_bits) skip_value = 0xfff; else skip_value = 0x3fff; if (16 <= deviceinfo [dev].prog_bits) rowlen = 16; else rowlen = 8; while (addr < addr0 + len0) { // Skip undefined locations or ignored values if (skip_value == pgmp [addr-addr0] || -1 == pgmp [addr-addr0]) { addr++; continue; } len = 1; while (len < rowlen && (addr + len) % rowlen && addr + len < addr0 + len0 && skip_value != pgmp [addr - addr0 + len] && -1 != pgmp [addr - addr0 + len]) len++; if (ihx32 == format) { if (addr32 != (addr & 0xffff0000)) { addr32 = addr & 0xffff0000; int sum = 0x02 + 0x04 + (addr32 >> 16) + (addr32 >> 24); f << ":02000004" << setw(4) << (addr32 >> 16) << setw(2) << (-sum & 0xff) << endl; } } else { // not ihx32 if (addr > 0xffff) { cerr << "ihx32 format needed for this data" << endl; return EX_USAGE; } } save_line (f, pgmp + (addr - addr0), addr, len, format); addr += len; } return EX_OK; } int hexfile::save (const char *name, enum hexfile::formats format, bool skip_ones) const { ofstream f (name); int e; unsigned long addr32 = 1; // flag that addr32 line must be output on first line if (unknown == format) { if (16 <= deviceinfo [dev].prog_bits) format = ihx32; else format = ihx16; } if (!f) { e = errno; cerr << name << ":unable to open save file:" << strerror (e) << endl; return EX_IOERR; } f << hex << setfill ('0') << setiosflags (ios::uppercase); e = save_region (f, pgm, 0, deviceinfo [dev].prog_size, format, skip_ones, addr32); if (EX_OK != e) return e; if (24 == deviceinfo [dev].prog_bits) // No ids for dspic30 e = EX_OK; else if (16 == deviceinfo [dev].prog_bits) e = save_region (f, ids, 0x200000, 8, format, skip_ones, addr32); else if (12 == deviceinfo [dev].prog_bits) // Save the backup osccal word to the ids too! e = save_region (f, ids, deviceinfo [dev].prog_size, 5, format, skip_ones, addr32); else e = save_region (f, ids, 0x2000, 4, format, skip_ones, addr32); if (EX_OK != e) return e; if (24 == deviceinfo [dev].prog_bits) e = save_region (f, conf, 0xf80000, deviceinfo [dev].conf_size, format, skip_ones, addr32); else if (16 == deviceinfo [dev].prog_bits) e = save_region (f, conf, 0x300000, deviceinfo [dev].conf_size, format, skip_ones, addr32); else if (12 == deviceinfo [dev].prog_bits) e = save_region (f, conf, 0xfff, deviceinfo [dev].conf_size, format, skip_ones, addr32); else e = save_region (f, conf, 0x2007, deviceinfo [dev].conf_size, format, skip_ones, addr32); if (EX_OK != e) return e; if (24 == deviceinfo [dev].prog_bits) e = save_region (f, data, 0x800000 - deviceinfo [dev].data_size, deviceinfo [dev].data_size, format, skip_ones, addr32); else if (16 == deviceinfo [dev].prog_bits) e = save_region (f, data, 0xf00000, deviceinfo [dev].data_size, format, skip_ones, addr32); else if (12 == deviceinfo [dev].prog_bits) e = EX_OK; // No 12 bit data areas implemented else e = save_region (f, data, 0x2100, deviceinfo [dev].data_size, format, skip_ones, addr32); if (EX_OK != e) return e; f << ":00000001FF" << endl; return EX_OK; } // Verify 8 bytes at the given address in all panels // available in the device. bool hexfile::verify18 (picport& pic, const short *pgmp, unsigned long addr, unsigned long len, unsigned long panel_size, bool verbose) const { // If we are not handling program memory, below 0x200000, we obviously // loop only once. Id and config memory must be written in single // panel mode. for (unsigned long panel = 0; addr < 0x200000 ? panel + addr < deviceinfo [dev].prog_size : 0 == panel; panel += panel_size) { unsigned long i, j; for (i = 0; i < len; ++i) if (-1 != pgmp [panel + i]) break; if (len == i) continue; // Find the last byte to verify for (j = len - 1; -1 == pgmp [panel + j]; --j) ; pic.setaddress (panel + addr + i); for (; i <= j; ++i) { int value = pic.command18 (picport::tread_inc); if (value != pgmp [panel + i] && -1 != pgmp [panel + i]) { if (verbose) { cerr << pic.port() << ":" << "0x" << hex << setfill('0') << setw(6) << panel + addr + i << ": panel " << (panel >> 13) << ", block " << setw(4) << addr << ", byte " << i << ": verification failed, read 0x" << setw(2) << value << ", should be 0x" << setw(2) << pgmp [panel + i] << dec << endl; } return false; } } } // for panels return true; } // PIC18 parts code programming. Do multi-panel programming. It is // assumed that correct mode is set before calling this method. Also // address parameter must be < panel size, ie. 8kB for original 18f parts. // Call with panel_size == prog_size if multipanel writes not used. int hexfile::program18 (picport& pic, const short *pgmp, unsigned long addr, unsigned long len, unsigned long panel_size) const { if (verify18 (pic, pgmp, addr, len, panel_size, false)) return 0; unsigned long count = 0; // Loop only once for single panel writes for (unsigned long panel = 0; addr < 0x200000 ? panel + addr < deviceinfo [dev].prog_size : 0 == panel; panel += panel_size) { pic.setaddress (panel + addr); for (unsigned long i = 0; i < len; i += 2) { picport::commands18 comm; if (i+2 < len) // Normal bytes of 8 byte block comm = picport::twrite_inc2; else if (addr < 0x200000 && panel + panel_size + addr < deviceinfo [dev].prog_size) // Last bytes do not need post increment comm = picport::twrite; else // Last bytes of last write need programming command comm = picport::twrite_prog; // For locations that do not need programming, pgm[] has value // -1. With &0xff operation, that becomes 0xff. This is fine, // as it is the erased state of flash memory, and no bits are // programmed to 0 state. pic.command18 (comm, (0xff & pgmp [panel + i]) | ((0xff & pgmp [panel + i + 1]) << 8)); count += 2; } // for bytes (words) } // for panels // The programming command was issued above, and now we need the NOP // command with programming delay. pic.command18 (picport::nop_prog, 0); if (!verify18 (pic, pgmp, addr, len, panel_size, true)) return -EX_IOERR; return count; } /* Locations are verified before and after programming, so unnecessary programming is avoided and errors are detected. PIC18 parts can only be programmed 8 locations at a time. */ // This is the 14 bit programming int hexfile::program_location (picport& pic, unsigned long addr, short word, bool isdata) const { int retval; if (-1 == word || (retval = pic.command (isdata ? picport::data_from_data : picport::data_from_prog)) == word) return NOT_PROGRAMMED; if (-1 == retval) { cerr << pic.port() << ':' << hex << setfill ('0') << setw (4) << addr << dec << ":unable to read pic while programming" << endl; return EX_IOERR; } pic.command (isdata ? picport::data_for_data : picport::data_for_prog, word); switch (deviceinfo [dev].prog_type) { case flash2: // pic16f77 pic.command (picport::beg_prog); pic.delay (1000*1000); // tprog = 1ms pic.command (picport::end_prog); break; case prom: // pic16c case eprom: pic.command (picport::beg_prog); usleep (10000); // Maximum needed programming time = 100 * 100 µs pic.command (picport::end_prog); break; case flash3: // pic16f876a if (0x2007 == addr) { pic.command (picport::beg_prog); usleep (10000); // tprog2 = 8ms } else { pic.command (picport::beg_prog_only); pic.delay (1000*1000); // tprog = 1ms pic.command (picport::end_prog_only); } break; case flash5: // pic16f88 pic.command (picport::beg_prog_only); pic.delay (1000*1000); pic.command (picport::end_prog_only); break; case flash4: pic.command (picport::beg_prog); pic.delay (6*1000*1000); break; case flash: case eeprom: pic.command (picport::beg_prog); usleep (10000); break; default: cerr << "Internal error: unknown memory type: " << int(deviceinfo [dev].prog_type) << endl; return EX_SOFTWARE; } // verify, but do not verify fuses if Code Protect bit is cleared! int read_val; if (word != (read_val = pic.command (isdata ? picport::data_from_data : picport::data_from_prog))) { cerr << pic.port() << ':' << hex << setw (4) << setfill ('0') << addr << ": programmed=" << setw (4) << setfill ('0') << word << ", read=" << setw (4) << setfill ('0') << read_val << dec << ":unable to verify pic while programming." << endl; if (pic.address () != 0x2007) { cerr << "Is code protection enabled, or does the chip need to be " << endl << "erased completely before programming?" << endl << "Use --erase option to disable code protection." << endl; return EX_IOERR; } else { cerr << "This is the configuration word, which often has hardwired" << endl << "bits and therefore does not verify. It also has the code" << endl << "protection bits, and if they were programmed to enabled" << endl << "state, verification fails. Therefore this error is ignored." << endl; } } return EX_OK; } typedef void (*sig_type)(int); void hexfile::reset_code_protection (picport& pic) { switch (deviceinfo [dev].prog_type) { case flash30: // dspic30f // Step 1 pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0x040100); // GOTO 0x100 pic.command30 (picport::SIX, 0); // NOP // Steps 2-7 only concern dspic30f601[0-4] mask 0 versions // What does that mean?? if (0) { // Step 2 pic.command30 (picport::SIX, 0x24008A); // pic.command30 (picport::SIX, 0x883B0A); // // Step 3 pic.command30 (picport::SIX, 0x200F80); // pic.command30 (picport::SIX, 0x880190); // pic.command30 (picport::SIX, 0x200067); // pic.command30 (picport::SIX, 0xEB0300); // // Step 4 pic.command30 (picport::SIX, 0x231010); // // Step 5 pic.command30 (picport::SIX, 0xBB0B96); // // Step 6 pic.command30 (picport::SIX, 0x200558); // MOV #0x55, W8 pic.command30 (picport::SIX, 0x883B38); // MOV W8, NVMKEY pic.command30 (picport::SIX, 0x200AA9); // MOV #0xAA, W9 pic.command30 (picport::SIX, 0x883B39); // MOV W9, NVMKEY // Step 7 pic.command30 (picport::SIX, 0xA8E761); // BSET NVMCON, #WR pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0); // NOP usleep (2000); pic.command30 (picport::SIX, 0xA9E761); // BCLR NVMCON, #WR pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0); // NOP } // Step 8 pic.command30 (picport::SIX, 0x2407FA); // MOV #0x407F, W10 pic.command30 (picport::SIX, 0x883B0A); // MOV W10, NVMCON // Step 9 pic.command30 (picport::SIX, 0x200558); // MOV #0x55, W8 pic.command30 (picport::SIX, 0x883B38); // MOV W8, NVMKEY pic.command30 (picport::SIX, 0x200AA9); // MOV #0xAA, W9 pic.command30 (picport::SIX, 0x883B39); // MOV W9, NVMKEY // Step 10 pic.command30 (picport::SIX, 0xA8E761); // BSET NVMCON, #WR pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0); // NOP usleep (2000); pic.command30 (picport::SIX, 0xA9E761); // BCLR NVMCON, #WR pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0); // NOP break; case flash18: // pic18f // new series has different erase algorithm if (!deviceinfo [dev].panel_size) { pic.setaddress (0x3c0005); pic.command18 (picport::twrite, 0x0F0F); // Write 0F0F to 3c0005h pic.setaddress (0x3c0004); pic.command18 (picport::twrite, 0x8787); // Write 8787 to 3c0004h pic.command18 (picport::instr, 0); // NOP pic.command18 (picport::nop_erase, 0); // NOP, delay break; } // fallthrough for original pic18f series case eprom18: // pic18c - unsupported pic.setaddress (0x3c0004); pic.command18 (picport::twrite, 0x0080); // Write 80h to 3c0004h pic.command18 (picport::instr, 0); // NOP pic.command18 (picport::nop_erase, 0); // NOP, delay break; case flash2: // pic16f77, pic12f // pic12f508, pic12f509 do not have load_conf, but full erase // needs another magic address thing. See 41227D. if (deviceinfo [dev].prog_bits == 12) { while (pic.address () != deviceinfo [dev].prog_size) pic.command (picport::inc_addr, addr_max); } else pic.command (picport::load_conf, 0x3fff); pic.command (picport::erase_prog); break; case flash3: // pic16f876a case flash5: // pic16f88 pic.command (picport::load_conf, 0x3fff); pic.command (picport::chip_erase); break; case flash4: // pic16f628a pic.command (picport::load_conf, 0x3fff); pic.command (picport::erase_prog); usleep (50000); pic.command (picport::erase_data); break; default: // eeprom, flash pic.command (picport::load_conf, 0x3fff); for (int i = 0; i < 7; i++) pic.command (picport::inc_addr); assert (0x2007 == pic.address ()); pic.command (picport::command1); pic.command (picport::command7); pic.command (picport::beg_prog); usleep (20000); pic.command (picport::command1); pic.command (picport::command7); // On my pic16f628, the above leaves data memory not erased, // if the code protection was not on. pic.command (picport::data_for_data, 0x3fff); pic.command (picport::erase_data); pic.command (picport::beg_prog); } usleep (50000); pic.reset (deviceinfo [dev].prog_bits == 12 ? 0xfff : 0); } int hexfile::program (picport &pic, bool reset, bool nopreserve) { int retval; sig_type save_t, save_q, save_i; save_t = signal (SIGTERM, term_handler); save_q = signal (SIGQUIT, term_handler); save_i = signal (SIGINT, term_handler); cout << "Device " << deviceinfo [dev].name << ", program memory: " << deviceinfo [dev].prog_size << ", data memory: " << deviceinfo [dev].data_size << "." << endl; if ((rom == deviceinfo [dev].data_type || 0 == deviceinfo [dev].data_size) && (rom == deviceinfo [dev].prog_type || 0 == deviceinfo [dev].prog_size)) { cerr << "This type of device has no programmable memory." << endl; return EX_USAGE; } // As PIC18 parts never have prog_preserved, it does not have to // be tested here. if (deviceinfo [dev].prog_preserved && !nopreserve) { if (!reset) { // Chip is not erased, so we just need to avoid programming // the reserved locations. for (unsigned long addr = deviceinfo [dev].prog_size - deviceinfo [dev].prog_preserved; addr != deviceinfo [dev].prog_size; ++addr) { cout << "Calibration word at " << hex << setfill('0') << setw(4) << addr << dec << " not programmed"; if (-1 != pgm [addr]) { pgm [addr] = -1; cout << " (value in input file ignored)"; } cout << endl; } if (deviceinfo [dev].prog_bits == 12) { // 12f508, 12f509 // Backup osccal word. unsigned long addr = deviceinfo [dev].prog_size + 4; cout << "Calibration word at " << hex << setfill('0') << setw(4) << addr << dec << " not programmed"; if (-1 != ids [addr - deviceinfo [dev].prog_size]) { ids [addr - deviceinfo [dev].prog_size] = -1; cout << " (value in input file ignored)"; } cout << endl; } } else { // We are erasing the chip. Read OSCCAL and other reserved // words off the device first. // Make sure we are in the program memory and below OSCCAL // address if (pic.address () > deviceinfo [dev].prog_size - deviceinfo [dev].prog_preserved) { if (deviceinfo [dev].prog_bits == 12) { // 12f508/509 reset to configuration word. if (pic.address () != 0xfff) pic.reset (0xfff); // We need to step them to address 0. if (pic.address () == 0xfff && pic.address () > deviceinfo [dev].prog_size - deviceinfo [dev].prog_preserved) pic.command (picport::inc_addr, addr_max); } else { if (pic.address ()) pic.reset (0); } } for (;;) { if (pic.address () >= deviceinfo [dev].prog_size - deviceinfo [dev].prog_preserved && pic.address () < deviceinfo [dev].prog_size) { int value = pic.command (picport::data_from_prog); if (-1 == value) { cerr << pic.port() << ':' << hex << setfill ('0') << setw (4) << pic.address () << dec << ":unable to read pic calibration words" << endl; return EX_IOERR; } cout << "Calibration word at 0x" << hex << setfill('0') << setw(4) << pic.address() << " preserved as 0x" << setfill('0') << setw(4) << value << dec; if (-1 != pgm [pic.address ()]) cout << " (value in input file ignored)"; cout << endl; pgm [pic.address ()] = value; } if (pic.address () + 1 == deviceinfo [dev].prog_size) break; pic.command (picport::inc_addr, addr_max); } // for if (deviceinfo [dev].prog_bits == 12) { // 12f508, 12f509 // Backup osccal word. for (;;) { if (pic.address () == deviceinfo [dev].prog_size + 4) { int value = pic.command (picport::data_from_prog); if (-1 == value) { cerr << pic.port() << ':' << hex << setfill ('0') << setw (4) << pic.address () << dec << ":unable to read pic calibration words" << endl; return EX_IOERR; } cout << "Calibration word at 0x" << hex << setfill('0') << setw(4) << pic.address() << " preserved as 0x" << setfill('0') << setw(4) << value << dec; if (-1 != ids [pic.address () - deviceinfo [dev].prog_size]) cout << " (value in input file ignored)"; cout << endl; ids [pic.address () - deviceinfo [dev].prog_size] = value; break; // Only 1 backup word } pic.command (picport::inc_addr, addr_max); } } // if 12f508 12f509 } } // As PIC18 parts never have config_mask, it does not have to be // tested here. if (deviceinfo [dev].config_mask && !nopreserve) { if (reset || -1 != conf [0]) { pic.command (picport::load_conf, 0); for (int i = 0; i < 7; ++i) pic.command (picport::inc_addr); assert (0x2007 == pic.address()); int value; if (-1 == (value = pic.command (picport::data_from_prog))) { cerr << pic.port() << ':' << hex << setfill ('0') << setw (4) << pic.address () << dec << ":unable to read pic calibration bits" << endl; return EX_IOERR; } value &= deviceinfo [dev].config_mask; cout << "Calibration bits 0x" << hex << setfill('0') << setw(4) << deviceinfo [dev].config_mask << " in configuration word preserved as 0x" << setfill('0') << setw(4) << value << dec << endl; if (-1 == conf [0]) conf [0] = 0x3fff; conf [0] = (conf [0] & ~deviceinfo [dev].config_mask) | value; } else { cout << "Calibration bits 0x" << hex << setfill('0') << setw(4) << deviceinfo [dev].config_mask << dec << " in configuration word not programmed" << endl; } } if (reset) { if (rom == deviceinfo [dev].prog_type || prom == deviceinfo [dev].prog_type || eprom == deviceinfo [dev].prog_type) { cerr << "I do not know how to erase this device." << endl; return EX_UNAVAILABLE; } reset_code_protection (pic); cout << "Erased and removed code protection." << endl; } if (deviceinfo [dev].prog_bits == 12) { // 12f508/509 reset to configuration word. if (pic.address () != 0xfff && pic.address () != 0) pic.reset (0xfff); // We need to step them to address 0. if (pic.address () == 0xfff) pic.command (picport::inc_addr, addr_max); } else { if (pic.address ()) pic.reset (0); } int count; if (rom == deviceinfo [dev].prog_type || 0 == deviceinfo [dev].prog_size) { cout << "Skipped burning program memory," << endl; } else { cout << "Burning program memory," << flush; count = 0; if (16 == deviceinfo [dev].prog_bits) { // Enable access to config memory pic.command18 (picport::instr, 0x8ea6); pic.command18 (picport::instr, 0x8ca6); pic.command18 (picport::instr, 0x86A6); if (deviceinfo [dev].panel_size) { // Configure device for multi-panel writes. pic.setaddress (0x3c0006); pic.command18 (picport::twrite, 0x0040); } else { // Disable multi-panel writes. pic.setaddress (0x3c0006); pic.command18 (picport::twrite, 0x0000); } // Enable access to program memory. pic.command18 (picport::instr, 0x8ea6); pic.command18 (picport::instr, 0x9ca6); pic.setaddress (0); } unsigned long addr = pic.address (); unsigned long panel_size = deviceinfo [dev].panel_size; if (!panel_size || panel_size > deviceinfo [dev].prog_size) panel_size = deviceinfo [dev].prog_size; while (addr < panel_size) { if (16 == deviceinfo [dev].prog_bits) { int len = deviceinfo [dev].write_size; retval = program18 (pic, pgm + addr, addr, len, panel_size); if (retval >= 0) count += retval; else return -retval; addr += len; } else { // 12 bit and 14 bit retval = program_location (pic, addr, pgm [addr], false); if (EX_OK == retval) ++count; else if (NOT_PROGRAMMED != retval) return retval; pic.command (picport::inc_addr, addr_max); addr = pic.address (); } if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } } cout << " " << count << " location" << (count != 1 ? "s" : "") << "," << endl; } if (rom == deviceinfo [dev].data_type || 0 == deviceinfo [dev].data_size) { cout << "skipped burning data memory," << endl; } else { cout << "burning data memory," << flush; count = 0; if (16 == deviceinfo [dev].prog_bits) { // Direct access to data EEPROM. pic.command18 (picport::instr, 0x9ea6); pic.command18 (picport::instr, 0x9ca6); } for (unsigned long addr = 0; addr < deviceinfo [dev].data_size; ++addr) { if (16 == deviceinfo [dev].prog_bits) { if (-1 == data [addr]) retval = NOT_PROGRAMMED; else { // Set the data EEPROM address pointer. pic.command18 (picport::instr, 0x0e00 | (addr & 0x00ff)); pic.command18 (picport::instr, 0x6ea9); pic.command18 (picport::instr, 0x0e00 | ((addr & 0xff00) >> 8)); pic.command18 (picport::instr, 0x6eaa); // Initiate a memory read. pic.command18 (picport::instr, 0x80a6); // Load data into the serial data holding register. pic.command18 (picport::instr, 0x50a8); pic.command18 (picport::instr, 0x6ef5); pic.command18 (picport::instr, 0x0000); int word = pic.command18 (picport::shift_out); if (word == data [addr]) retval = NOT_PROGRAMMED; else { // Load the data to be written. pic.command18 (picport::instr, 0x0e00 | (data [addr] & 0x00ff)); pic.command18 (picport::instr, 0x6ea8); // Enable memory writes. pic.command18 (picport::instr, 0x84a6); // Perform required sequence. pic.command18 (picport::instr, 0x0e55); pic.command18 (picport::instr, 0x6ea7); pic.command18 (picport::instr, 0x0eaa); pic.command18 (picport::instr, 0x6ea7); // Initiate write. pic.command18 (picport::instr, 0x82a6); // Poll EECON1 WR bit, repeat until the bit is clear. do { if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } pic.command18 (picport::instr, 0x50a6); pic.command18 (picport::instr, 0x6ef5); pic.command18 (picport::instr, 0x0000); word = pic.command18 (picport::shift_out); } while (word & 2); // Disable writes. pic.command18 (picport::instr, 0x94a6); // Read to verify // Initiate a memory read. pic.command18 (picport::instr, 0x80a6); // Load data into the serial data holding register. pic.command18 (picport::instr, 0x50a8); pic.command18 (picport::instr, 0x6ef5); pic.command18 (picport::instr, 0x0000); word = pic.command18 (picport::shift_out); if (word == data [addr]) retval = EX_OK; else { cerr << pic.port() << ':' << hex << setw (6) << setfill ('0') << 0xf00000 + addr << ": programmed=" << setw (2) << setfill ('0') << data [addr] << ", read=" << setw (2) << setfill ('0') << word << dec << ":unable to verify pic data eeprom while programming." << endl; retval = EX_IOERR; } } } } else if (12 == deviceinfo [dev].prog_bits) { cerr << "12 bit microcontroller data memory unimplemented." << endl; retval = NOT_PROGRAMMED; got_signal = 1; } else { // 14 bit retval = program_location (pic, 0x2100 + addr, data [addr], true); pic.command (picport::inc_addr); } if (EX_OK == retval) ++count; else if (NOT_PROGRAMMED != retval) return retval; if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } } cout << " " << count << " location" << (count != 1 ? "s" : "") << "," << endl; } cout << "burning id words," << flush; count = 0; if (16 == deviceinfo [dev].prog_bits) { // Enable access to config memory pic.command18 (picport::instr, 0x8ea6); pic.command18 (picport::instr, 0x8ca6); pic.command18 (picport::instr, 0x86A6); // Disable multi-panel writes. pic.setaddress (0x3c0006); pic.command18 (picport::twrite, 0x0000); // Enable access to code memory. pic.command18 (picport::instr, 0x8ea6); pic.command18 (picport::instr, 0x9ca6); retval = program18 (pic, ids, 0x200000, 8, 8); if (retval >= 0) count += retval; else return -retval; } else if (12 == deviceinfo [dev].prog_bits) { while (pic.address () != deviceinfo [dev].prog_size) pic.command (picport::inc_addr, addr_max); // id words and backup osccal word while (pic.address () < deviceinfo [dev].prog_size + 5) { retval = program_location (pic, pic.address (), ids [pic.address () - deviceinfo [dev].prog_size], false); if (EX_OK == retval) ++count; else if (NOT_PROGRAMMED != retval) return retval; pic.command (picport::inc_addr, addr_max); if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } } } else { // 14 bit pic.command (picport::load_conf, 0x3fff); // dummy value while (pic.address () < 0x2004) { retval = program_location (pic, pic.address (), ids [pic.address () - 0x2000], false); if (EX_OK == retval) ++count; else if (NOT_PROGRAMMED != retval) return retval; pic.command (picport::inc_addr); if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } } } // 14 bit cout << " " << count << " location" << (count != 1 ? "s" : "") << "," << endl; cout << "burning fuses," << flush; count = 0; if (16 == deviceinfo [dev].prog_bits) { // Enable access to config memory pic.command18 (picport::instr, 0x8ea6); pic.command18 (picport::instr, 0x8ca6); // Position the program counter pic.command18 (picport::instr, 0xef00); pic.command18 (picport::instr, 0xf800); // GOTO 100000h bool printerr = true; for (unsigned long addr = 0; addr < deviceinfo [dev].conf_size; ++addr) { if (-1 == conf [addr]) continue; pic.setaddress (0x300000 + addr); int word = pic.command18 (picport::tread); if (word == conf [addr]) continue; word = conf [addr]; if (addr & 1) word <<= 8; pic.command18 (picport::twrite_prog, word); pic.command18 (picport::nop_prog, 0); word = pic.command18 (picport::tread); if (word != conf [addr]) { cerr << pic.port() << ":" << "0x" << hex << setfill('0') << setw(6) << 0x300000 + addr << ": configuration byte verification failed, read 0x" << setw(2) << word << ", should be 0x" << setw(2) << conf [addr] << dec << endl; if (printerr) { printerr = false; cerr << "This is a configuration byte, which often has hardwired" << endl << "bits and therefore does not verify. It also may have code" << endl << "protection bits, and if they were programmed to enabled" << endl << "state, verification may fail. Therefore this error is ignored." << endl; } } ++count; } } else if (12 == deviceinfo [dev].prog_bits) { // 12f508/12f509 reset to configuration word, // and the only time the config word is accessable, // is right after the reset. pic.reset (0xfff); // Only one config word. retval = program_location (pic, pic.address (), conf [pic.address () - 0xfff], false); if (EX_OK == retval) ++count; else if (NOT_PROGRAMMED != retval) return retval; } else { // 14 bit pic.command (picport::inc_addr); pic.command (picport::inc_addr); while (pic.address () + 1 < 0x2007 + deviceinfo [dev].conf_size) { pic.command (picport::inc_addr); retval = program_location (pic, pic.address (), conf [pic.address () - 0x2007], false); if (EX_OK == retval) ++count; else if (NOT_PROGRAMMED != retval) return retval; } // pic12f635 and friends need to reset write latches, // but as this is the last operation on them, no need // to do that. } // 14 bit cout << " " << count << " location" << (count != 1 ? "s" : "") << "," << endl; cout << "done." << endl; signal (SIGTERM, save_t); signal (SIGQUIT, save_q); signal (SIGINT, save_i); if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } return EX_OK; } int hexfile::read_code (picport &pic, short *pgmp, unsigned long addr, unsigned long len) { time_t tv1 = time(0); // 14 bit and 12 bit parts must make sure the address // is correct before calling this function. if (16 == deviceinfo [dev].prog_bits) pic.setaddress (addr); for (unsigned long i = 0; i != len; ++i) { assert (pic.address () == addr + i); time_t tv2 = time(0); if (tv2 >= tv1 + 2) { tv1 = tv2; cerr << "\r" << hex << setfill('0') << setw(4) << pic.address () << dec << " \r"; } if (16 == deviceinfo [dev].prog_bits) { pgmp [i] = pic.command18 (picport::tread_inc); } else if (12 == deviceinfo [dev].prog_bits) { pgmp [i] = pic.command (picport::data_from_prog) & 0xfff; pic.command (picport::inc_addr, addr_max); } else { // 14 bit pgmp [i] = pic.command (picport::data_from_prog); pic.command (picport::inc_addr); } if (-1 == pgmp [i]) { cerr << hex << setfill ('0') << setw (4) << addr + i << dec << ":unable to read pic" << endl; return EX_IOERR; } if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } } return EX_OK; } int hexfile::read (picport &pic) { sig_type save_t, save_q, save_i; save_t = signal (SIGTERM, term_handler); save_q = signal (SIGQUIT, term_handler); save_i = signal (SIGINT, term_handler); cout << "Device " << deviceinfo [dev].name << ", program memory: " << deviceinfo [dev].prog_size; if (rom == deviceinfo [dev].prog_type && deviceinfo [dev].prog_size) cout << " (rom)"; cout << ", data memory: " << deviceinfo [dev].data_size; if (rom == deviceinfo [dev].data_type && deviceinfo [dev].data_size) cout << " (rom)"; cout << "." << endl; int e; if (deviceinfo [dev].prog_bits == 12) { // 12f508/509 reset to configuration word. if (pic.address () != 0xfff && pic.address () != 0) pic.reset (0xfff); // We need to step them to address 0. if (pic.address () == 0xfff) pic.command (picport::inc_addr, addr_max); } else { if (pic.address ()) pic.reset (0); } if (0 == deviceinfo [dev].prog_size) { cout << "Skipped reading program memory," << endl; } else { cout << "Reading program memory," << endl; e = read_code (pic, pgm, 0, deviceinfo [dev].prog_size); if (EX_OK != e) return e; } if (0 == deviceinfo [dev].data_size) { cout << "skipped reading data memory," << endl; } else { cout << "reading data memory," << endl; if (16 == deviceinfo [dev].prog_bits) { // Direct access to data EEPROM. pic.command18 (picport::instr, 0x9ea6); pic.command18 (picport::instr, 0x9ca6); } for (unsigned long addr = 0; addr < deviceinfo [dev].data_size; ++addr) { if (16 == deviceinfo [dev].prog_bits) { // Set the data EEPROM address pointer. pic.command18 (picport::instr, 0x0e00 | (addr & 0x00ff)); pic.command18 (picport::instr, 0x6ea9); pic.command18 (picport::instr, 0x0e00 | ((addr & 0xff00) >> 8)); pic.command18 (picport::instr, 0x6eaa); // Initiate a memory read. pic.command18 (picport::instr, 0x80a6); // Load data into the serial data holding register. pic.command18 (picport::instr, 0x50a8); pic.command18 (picport::instr, 0x6ef5); data [addr] = pic.command18 (picport::shift_out); } else if (12 == deviceinfo [dev].prog_bits) { cerr << "12 bit microcontroller data memory unimplemented." << endl; got_signal = 1; } else { // 14 bit assert (addr == pic.address () % deviceinfo [dev].data_size); data [addr] = pic.command (picport::data_from_data); pic.command (picport::inc_addr); } if (-1 == data [addr]) { cerr << pic.port() << ':' << hex << setfill ('0') << setw (4) << addr << dec << ":unable to read pic data memory" << endl; return EX_IOERR; } if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } } } cout << "reading id words," << endl; if (24 == deviceinfo [dev].prog_bits) { // no ids in dspic30 e = EX_OK; } else if (16 == deviceinfo [dev].prog_bits) { e = read_code (pic, ids, 0x200000, 8); } else if (12 == deviceinfo [dev].prog_bits) { while (pic.address () != deviceinfo [dev].prog_size) pic.command (picport::inc_addr, addr_max); // 12f508/12f509 backup osccal is included in ids e = read_code (pic, ids, deviceinfo [dev].prog_size, 5); } else { pic.command (picport::load_conf, 0); e = read_code (pic, ids, 0x2000, 4); } if (EX_OK != e) return e; // fuses cout << "reading fuses," << endl; if (24 == deviceinfo [dev].prog_bits) { e = read_code (pic, conf, 0xf80000, deviceinfo [dev].conf_size); } else if (16 == deviceinfo [dev].prog_bits) { e = read_code (pic, conf, 0x300000, deviceinfo [dev].conf_size); } else if (12 == deviceinfo [dev].prog_bits) { // Only reset allows us to access the config word. pic.reset (0xfff); e = read_code (pic, conf, 0xfff, deviceinfo [dev].conf_size); } else { pic.command (picport::inc_addr); pic.command (picport::inc_addr); pic.command (picport::inc_addr); e = read_code (pic, conf, 0x2007, deviceinfo [dev].conf_size); } if (EX_OK != e) return e; cout << "done." << endl; signal (SIGTERM, save_t); signal (SIGQUIT, save_q); signal (SIGINT, save_i); if (got_signal) { cerr << "Exiting." << endl; return EX_UNAVAILABLE; } return EX_OK; } int hexfile::setdevice (picport &pic, int& d) { if (-1 == d && -1 != dev) d = dev; if (-1 == d) { // Read version information off the chip at address 0x2006 pic.command (picport::load_conf, 0); for (int i = 0; i < 6; ++i) pic.command (picport::inc_addr); assert (0x2006 == pic.address()); int version = 0; int value = pic.command (picport::data_from_prog); int family = 14; if (0x3fff == value) { // Either the device is old model and does not have id bits, or // it is 18F device and needs another programming algorithm. // Let's try that first and only default if it fails. // Enable access to program memory. pic.command18 (picport::instr, 0x8ea6); pic.command18 (picport::instr, 0x9ca6); pic.setaddress (0x3ffffe); value = pic.command18 (picport::tread_inc, 0); int v1 = pic.command18 (picport::tread, 0); if (-1 != value && -1 != v1) { value |= (v1 << 8); if (0xffff != value) family = 16; } if (16 != family) { // If may be dspic30 then pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0x040100); // GOTO 0x100 pic.command30 (picport::SIX, 0); // NOP pic.setaddress30 (0xff0000); // Step 3 pic.command30 (picport::SIX, 0xEB0380); // CLR W7 pic.command30 (picport::SIX, 0xBA0BB6); // TBLRDL [W6++], [W7] pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0x883C20); // MOV W0, VISI pic.command30 (picport::SIX, 0); // NOP // Step 4 value = pic.command30 (picport::REGOUT); // pic.command30 (picport::SIX, 0); // NOP // Step 5 pic.command30 (picport::SIX, 0x040100); // GOTO 0x100 pic.command30 (picport::SIX, 0); // NOP // Step 3 pic.command30 (picport::SIX, 0xEB0380); // pic.command30 (picport::SIX, 0xBA0BB6); // pic.command30 (picport::SIX, 0); // NOP pic.command30 (picport::SIX, 0x883C20); // pic.command30 (picport::SIX, 0); // NOP // Step 4 version = pic.command30 (picport::REGOUT); // pic.command30 (picport::SIX, 0); // NOP // Step 5 pic.command30 (picport::SIX, 0x040100); // GOTO 0x100 pic.command30 (picport::SIX, 0); // NOP cerr << hex << "value: 0x" << setw(4) << setfill('0') << value << " version: 0x" << setw(4) << setfill('0') << version << dec << endl; if (0xffff != value && 0xffff != version) family = 24; else value = -1; } } if (-1 == value) { cerr << pic.port() << ':' << hex << setfill ('0') << setw (4) << pic.address () << dec << ":unable to read pic device id" << endl; return EX_IOERR; } d = 0; if (0xffff == value) cout << pic.port() << ": old device does not have id, defaulting to " << deviceinfo [d].name << endl; else for (;;++d) { if (d >= int(sizeof (hexfile::deviceinfo) / sizeof (hexfile::deviceinfo [0]))) { d = 0; cout << pic.port() << ": "; if (16 == family) cout << "pic18 "; else if (24 == family) cout << "dspic30 "; cout << "device id 0x" << hex << setfill ('0') << setw (4) << value; if (24 == family) cout << " revision 0x" << setfill ('0') << setw (4) << version; cout << dec << " unknown, exiting." << endl; return EX_PROTOCOL; } if (24 == family) { if (-1 != deviceinfo [d].device_id && deviceinfo [d].prog_bits == family && deviceinfo [d].device_id == value) { cout << pic.port() << ": id 0x" << hex << setfill ('0') << setw(4) << value << ": detected " << deviceinfo [d].name << " version 0x" << setw (4) << version << dec << endl; break; } } else { // Some devices like 18f2423, 2523, 4423 and 4523 can be detected // from the set revision high bit. int mask = 0xffe0 | (0x0010 & deviceinfo [d].device_id); //if (-1 != deviceinfo [d].device_id && (mask & 0x0010)) { // cerr << deviceinfo[d].name << " has version bit in mask\n"; //} if (-1 != deviceinfo [d].device_id && deviceinfo [d].prog_bits == family && (deviceinfo [d].device_id & mask) == (value & mask)) { cout << pic.port() << ": id 0x" << hex << setfill ('0') << setw(4) << value << ": detected " << deviceinfo [d].name << " version 0x" << setw (2) << (value & 0x1f & ~mask) << dec << endl; break; } } } } else if (d < 0 || d >= int(sizeof (deviceinfo) / sizeof (deviceinfo [0]))) { cerr << "Internal error: invalid device id " << d << endl; return EX_SOFTWARE; }; dev = d; if (pgm) delete [] pgm; if (data) delete [] data; pgm = data = 0; if (deviceinfo [dev].prog_size) { pgm = new short [deviceinfo [dev].prog_size]; if (!pgm) { cerr << "Out of memory, trying to allocate " << deviceinfo [dev].prog_size * sizeof (short) << " bytes" << endl; return EX_UNAVAILABLE; } } if (deviceinfo [dev].data_size) { data = new short [deviceinfo [dev].data_size]; if (!data) { cerr << "Out of memory, trying to allocate " << deviceinfo [dev].data_size * sizeof (short) << " bytes" << endl; return EX_UNAVAILABLE; } } unsigned long i; for (i = 0; i < deviceinfo [dev].prog_size; ++i) pgm [i] = -1; for (i = 0; i < deviceinfo [dev].data_size; ++i) data [i] = -1; assert (deviceinfo [dev].conf_size <= 16); for (i = 0; i < 16; ++i) conf [i] = -1; for (i = 0; i < 8; ++i) ids [i] = -1; if (deviceinfo [dev].prog_bits == 12) // 12f508 12f509 addr_max = deviceinfo [dev].prog_size * 2; else addr_max = 0; return EX_OK; } // Couple of statics in hexfile class. int hexfile::find_device (const char *name) { if (!name) return -1; for (unsigned d = 0; d < sizeof (deviceinfo) / sizeof (struct hexfile::devinf); ++d) if (!strcasecmp (hexfile::deviceinfo [d].name, name)) return d; return -1; } void hexfile::print_devices () { for (unsigned d = 0; d < sizeof (hexfile::deviceinfo) / sizeof (struct hexfile::devinf); ++d) { if (12 == deviceinfo [d].prog_bits) continue; if (d) cerr << ", "; cerr << deviceinfo [d].name; if (-1 != deviceinfo [d].device_id) cerr << "*"; } cerr << endl << "* = autodetected" << endl; } picprog-1.9.1/main.cc0000644000076500007650000001451311361223522013056 0ustar jaakkome/* -*- c++ -*- This is Picprog, Microchip PIC programmer software for the serial port device. Copyright © 1997,2002,2003,2004,2006,2008,2010 Jaakko Hyvätti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #include #include #include #include #include #include #include "hexfile.h" #include "program.h" using namespace std; program prog; char short_opts [] = "d:p:i:o:c:qh?"; static const char * getenv_default (const char *var, const char *def) { const char *val = getenv (var); if (val && *val) return val; return def; } int main (int argc, char **argv) { int opt_warranty = 0; int opt_copying = 0; int opt_quiet = 0; int opt_usage = 0; int opt_format = hexfile::unknown; const char *opt_port = getenv_default ("PIC_PORT", "/dev/ttyS0"); const char *opt_input = NULL; const char *opt_output = NULL; const char *opt_cc = NULL; int opt_skip = 0; int opt_erase = 0; int opt_burn = 0; int opt_calibration = 0; int opt_nordtsc = 1; int opt_slow = 0; int opt_reboot = 0; int opt_hardware = (int)(picport::jdm); // Auto ident (-1) is the default, or if that fails, first device (0) int opt_device = hexfile::find_device (getenv ("PIC_DEVICE")); struct option long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"warranty", no_argument, &opt_warranty, 1}, {"copying", no_argument, &opt_copying, 1}, {"help", no_argument, NULL, 'h'}, {"device", required_argument, NULL, 'd'}, {"pic-serial-port", required_argument, NULL, 'p'}, {"input-hexfile", required_argument, NULL, 'i'}, {"output-hexfile", required_argument, NULL, 'o'}, {"ihx32", no_argument, &opt_format, hexfile::ihx32}, {"ihx16", no_argument, &opt_format, hexfile::ihx16}, {"ihx8m", no_argument, &opt_format, hexfile::ihx8m}, {"cc-hexfile", required_argument, NULL, 'c'}, {"skip-ones", no_argument, &opt_skip, 1}, {"erase", no_argument, &opt_erase, 1}, {"burn", no_argument, &opt_burn, 1}, {"force-calibration", no_argument, &opt_calibration, 1}, {"nordtsc", no_argument, &opt_nordtsc, 1}, {"rdtsc", no_argument, &opt_nordtsc, 0}, {"slow", no_argument, &opt_slow, 1}, {"reboot", no_argument, &opt_reboot, 1}, {"jdm", no_argument, &opt_hardware, (int)(picport::jdm)}, {"k8048", no_argument, &opt_hardware, (int)(picport::k8048)}, {0, 0, 0, 0} }; int optc; prog.init (argv); while (0 <= (optc = getopt_long (argc, argv, short_opts, long_opts, NULL))) switch (optc) { case 0: break; case 'd': if (!strcmp (optarg, "auto")) opt_device = -1; else if (-1 == (opt_device = hexfile::find_device (optarg))) opt_usage = 1; break; case 'p': opt_port = optarg; break; case 'i': opt_input = optarg; break; case 'o': opt_output = optarg; break; case 'c': opt_cc = optarg; break; case 'q': opt_quiet = 1; break; default: // -? -h --help unknown flag opt_usage = 1; } if (!opt_quiet || opt_warranty || opt_copying || opt_usage) // Locale charset should be respected here. cerr << "Picprog version 1.9.1, Copyright © 2010 Jaakko Hyvätti \n" "Picprog comes with ABSOLUTELY NO WARRANTY; for details\n" "type `" << prog.name << " --warranty'. This is free software,\n" "and you are welcome to redistribute it under certain conditions;\n" "type `" << prog.name << " --copying' for details.\n\n"; if (opt_copying) prog.copying (); if (opt_warranty) prog.warranty (); if (opt_usage) { cerr << "Full documentation is at " "" << endl << "The author may be contacted at:" << endl << endl << "Email: Jaakko.Hyvatti@iki.fi" << endl << "URL: http://www.iki.fi/hyvatti/" << endl << endl << "Supported devices:" << endl; hexfile::print_devices (); cerr << endl; prog.usage (long_opts, short_opts); } if (opt_warranty || opt_copying || opt_usage) return EX_OK; if (!opt_input && !opt_output && !opt_erase) { cerr << "Please specify either input or output hexfile or --erase option." << endl; prog.usage (long_opts, short_opts); } if (opt_cc && !opt_input) { cerr << "Carbon copy does not make sense without input file." << endl; prog.usage (long_opts, short_opts); } picport pic (opt_port, opt_nordtsc, opt_slow, opt_reboot, picport::hardware_types(opt_hardware)); // if both input and output files are specified, first program the device // and then read it. if (opt_input || opt_erase) { hexfile mem; int retval; if (EX_OK != (retval = mem.setdevice (pic, opt_device))) return retval; if (opt_input && EX_OK != (retval = mem.load (opt_input))) return retval; if (opt_burn) { if (EX_OK != (retval = mem.program (pic, opt_erase, opt_calibration))) return retval; } else cout << "No --burn option specified, device not programmed.\n"; if (opt_input && opt_cc) if (EX_OK != (retval = mem.save (opt_cc, hexfile::formats (opt_format), opt_skip))) return retval; } if (opt_output) { hexfile mem; int retval; if (EX_OK != (retval = mem.setdevice (pic, opt_device))) return retval; if (EX_OK != (retval = mem.read (pic))) return retval; if (EX_OK != (retval = mem.save (opt_output, hexfile::formats (opt_format), opt_skip))) return retval; } return EX_OK; } picprog-1.9.1/picport.cc0000644000076500007650000004402711361217060013615 0ustar jaakkome/* -*- c++ -*- This is Picprog, Microchip PIC programmer software for the serial port device. Copyright © 1997,2002,2003,2004,2006,2007,2008,2010 Jaakko Hyvätti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "picport.h" using namespace std; #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif unsigned int picport::tsc_1000ns = 0; // Data bitrate delay, ns. // Cable delay is tested and this value adjusted when port is opened. int picport::cable_delay = 0; // Set this to -1 if you want to use nanosleep when running as root. // This only works with 2.4 kernels, 2.6 series kernels no more work. int picport::use_nanosleep = 0; // static bool disable_interrupts = 1; void picport::set_clock_data (int rts, int dtr) { if (hardware == k8048) { rts = !rts; dtr = !dtr; } // Before first call to set_clock_data, read the modem status like this: // ioctl (fd, TIOCMGET, &modembits); if (rts) modembits |= TIOCM_RTS; else modembits &= ~TIOCM_RTS; if (dtr) modembits |= TIOCM_DTR; else modembits &= ~TIOCM_DTR; if (0 > ioctl (fd, TIOCMSET, &modembits)) { int e = errno; tcsetattr (fd, TCSANOW, &saved); cerr << "Unable to set RTS/DTR on tty " << portname << ":" << strerror (e) << endl; exit (EX_IOERR); } } void picport::set_vpp (int vpp) { if (hardware == k8048) vpp = !vpp; if (0 > ioctl (fd, vpp ? TIOCSBRK : TIOCCBRK, 0)) { int e = errno; if (vpp) ioctl (fd, TIOCCBRK, 0); tcsetattr (fd, TCSANOW, &saved); cerr << "Unable to " << (vpp ? "start" : "stop") << " break on tty " << portname << ":" << strerror (e) << endl; exit (EX_IOERR); } } picport::picport (const char *tty, bool nordtsc, bool slow, bool reboot, hardware_types h) : addr (0), debug_on (0), hardware (h) { for (int i = 0; i < 16; ++i) W [i] = 0; portname = new char [strlen (tty) + 1]; strcpy (portname, tty); if (0 > (fd = open (tty, O_RDWR|O_NOCTTY|O_NONBLOCK))) { int e = errno; cerr << "Unable to open tty " << tty << ":" << strerror (e) << endl; exit (EX_IOERR); } tcgetattr (fd, &saved); termstate = saved; termstate.c_iflag = IGNBRK | IGNPAR; termstate.c_oflag = 0; termstate.c_cflag = B9600 | CS8 | CREAD | CLOCAL; termstate.c_lflag = 0; tcsetattr (fd, TCSANOW, &termstate); // Initialize lines for programming // RTS/DTR low, sleep and then TxD high (program voltage) ioctl (fd, TIOCCBRK, 0); // Before first call to set_clock_data, read the modem status. ioctl (fd, TIOCMGET, &modembits); modembits &= ~(TIOCM_RTS | TIOCM_DTR); ioctl (fd, TIOCMSET, &modembits); usleep (1000); // Check the CTS. If it is up, even when we just lowered DTR, // we probably are not talking to a JDM type programmer. int i = 0; ioctl (fd, TIOCMGET, &i); if (i & TIOCM_CTS) { tcsetattr (fd, TCSANOW, &saved); cerr << tty << ":CTS is high, probably we are not connected to a programmer but a modem or terminal." << endl; exit (EX_IOERR); } struct sched_param scp; scp.sched_priority = sched_get_priority_min (SCHED_FIFO); // sched_get_priority_max() // scp.sched_priority = 50; cerr << "Trying realtime priority " << scp.sched_priority << endl; if (sched_setscheduler (0, SCHED_FIFO, &scp)) { cerr << "Cannot use real time scheduling: " << strerror(errno) << endl; // Not root. Cannot use realtime scheduling. use_nanosleep = 0; } if (iopl (3)) disable_interrupts = 0; #ifdef CPU_SETSIZE // When computing the delay loops, we do not want the cpu's to change. // Pick the first cpu in the current allowed set. cpu_set_t new_mask; cpu_set_t cur_mask; CPU_ZERO(&cur_mask); CPU_ZERO(&new_mask); if (sched_getaffinity(0, sizeof (cur_mask), &cur_mask) < 0) { tcsetattr (fd, TCSANOW, &saved); cerr << "Getting affinity functions do not work." << endl; exit (EX_IOERR); } for (int cpuno = 0; cpuno < CPU_SETSIZE; ++cpuno) if (CPU_ISSET (cpuno, &cur_mask)) { CPU_SET (cpuno, &new_mask); sched_getaffinity (0, sizeof (new_mask), &new_mask); // We want to print informative line only if we really // have multiple cpu's. for (int cpuno1 = cpuno+1; cpuno1 < CPU_SETSIZE; ++cpuno1) if (CPU_ISSET (cpuno1, &cur_mask)) { cerr << "Bound to CPU " << cpuno << endl; break; } } #endif // CPU_SETSIZE #ifdef RDTSC_WORKS if (!nordtsc && !use_nanosleep && !tsc_1000ns) { // Read /proc/cpuinfo for clock speed, or if that fails, try our // own test. ifstream cpui ("/proc/cpuinfo"); string w; unsigned int mhz = 1; // 1MHz is just a flag that tsc was found while (cpui) { cpui >> w; if ("MHz" == w) { unsigned int tmp; // Read just the integer part. No need for the rest. cpui >> w >> tmp; // Update this when we have 100 GHz CPUs. if (tmp >= 4 && tmp <= 100000) mhz = tmp; } if ("tsc" == w && mhz) { // tsc capability found. Use it. tsc_1000ns = mhz; break; } } // If the /proc fs did not contain clock speed but indicated // tsc capability, test the approximate clock speed. if (1 == tsc_1000ns) { // Loop the test 20 times, and select the smallest count. for (int recount = 0; recount < 20; ++recount) { struct timeval tv1, tv2; unsigned long a1, d1, a2, d2; // Wait for when a microsecond changes gettimeofday (&tv2, 0); do { gettimeofday (&tv1, 0); } while (tv2.tv_usec == tv1.tv_usec); asm volatile("rdtsc":"=a" (a1), "=d" (d1)); tv1.tv_usec += 1000; if (tv1.tv_usec >= 1000000) { tv1.tv_usec -= 1000000; tv1.tv_sec ++; } do { gettimeofday (&tv2, 0); } while (tv2.tv_sec < tv1.tv_sec || (tv2.tv_sec == tv1.tv_sec && tv2.tv_usec < tv1.tv_usec)); asm volatile("rdtsc":"=a" (a2), "=d" (d2)); if (a2 < a1) d2 --; a2 -= a1; a2 &= 0xffffffff; // for x86_64 d2 -= d1; if (d2) continue; a2 /= 1000; if (tsc_1000ns <= 1 || tsc_1000ns > a2) tsc_1000ns = a2; } if (tsc_1000ns <= 1) { tcsetattr (fd, TCSANOW, &saved); cerr << "Unable to determine CPU clock speed for delay loops." << endl; exit (EX_IOERR); } } if (tsc_1000ns >= 1) { cout << "CPU clock speed: " << tsc_1000ns << " MHz" << endl; } } #endif if (tsc_1000ns > 1 && disable_interrupts) cerr << "Disable interrupts during delays." << endl; if (reboot) { // Power off any microcontroller that may be running a program. cerr << "Power off." << endl; set_clock_data (1, 1); set_vpp (1); usleep (500000); // 0.5s delay should discharge Vdd. } // /MCLR must go down for a while first set_vpp (0); usleep (10); // Power up set_clock_data (0, 0); set_vpp (1); // Charge Vdd usleep (25000); // Detect delays that are needed for cable lenght bool successful_echo = false; for (int i = 1; i <= 100; ++i) { int data_out = i & 1; // toggle data, keep clock off / power on if (data_out) modembits |= TIOCM_DTR; else modembits &= ~TIOCM_DTR; ioctl (fd, TIOCMSET, &modembits); delay (cable_delay); int data_in; ioctl (fd, TIOCMGET, &data_in); data_in = 0 != (data_in & TIOCM_CTS); delay (1000000); successful_echo = data_out == data_in; if (!successful_echo) cable_delay += 100; // Another 100 ns added for cable length ioctl (fd, TIOCMGET, &data_in); data_in = 0 != (data_in & TIOCM_CTS); if (data_out != data_in) { ioctl (fd, TIOCCBRK, 0); tcsetattr (fd, TCSANOW, &saved); cerr << "No JDM compatible hardware detected." << endl; exit (EX_IOERR); } } set_clock_data (0, 0); if (!successful_echo) { ioctl (fd, TIOCCBRK, 0); tcsetattr (fd, TCSANOW, &saved); cerr << "Cable too long." << endl; exit (EX_IOERR); } cable_delay += 100; // Another 100 ns added just for safety if (slow && cable_delay < 10000) cable_delay = 10000; if (1 == use_nanosleep) cerr << "Using " << cable_delay << " ns delays with real time priority." << endl; else if (tsc_1000ns > 1) cerr << "Using " << cable_delay << " ns delays." << endl; else if (cable_delay > 1000) cerr << "Using " << ((cable_delay + 999) / 1000) << " µs delays." << endl; else cerr << "Using >1 µs delays. --rdtsc may work for faster timings." << endl; } picport::~picport () { set_vpp (0); usleep (1); tcsetattr (fd, TCSANOW, &saved); close (fd); delete [] portname; } void picport::reset (unsigned long reset_address) { set_clock_data (0, 0); usleep (100); // Make sure we have the power there. set_vpp (0); usleep (50); set_vpp (1); usleep (10); addr = reset_address; } void picport::delay (long ns) { if (1 == use_nanosleep) { timespec ts = {ns / 1000000000, ns % 1000000000}, ts2; while (nanosleep (&ts, &ts2) && EINTR == errno) ts = ts2; return; } #ifdef RDTSC_WORKS if (tsc_1000ns > 1) { unsigned long a1, d1, a2, d2; if (ns <= 10000 && disable_interrupts) asm volatile("pushf; cli"); asm volatile("rdtsc":"=a" (a1), "=d" (d1)); d2 = d1; if (ns > 10000) // This is not as accurate but does not overflow a2 = 0xffffffff & (a1 + 1 + (ns+999)/1000*tsc_1000ns); else a2 = 0xffffffff & (a1 + 1 + (ns*tsc_1000ns + 999) / 1000); if (a2 < a1) d2++; do { asm volatile("rdtsc":"=a" (a1), "=d" (d1)); } while (d1 < d2 || (d1 == d2 && a1 < a2)); if (ns <= 10000 && disable_interrupts) asm volatile("popf"); return; } // Fall back to gettimeofday() if tsc is not available. #endif // RDTSC_WORKS // Delay loop that should take more than a microsecond to execute. // Check the real time clock and break out if at least the specified // number of microseconds has gone. struct timeval tv1, tv2; gettimeofday (&tv2, 0); tv2.tv_usec += 1 + (ns + 999)/1000; if (tv2.tv_usec >= 1000000) { tv2.tv_usec -= 1000000; tv2.tv_sec++; } do { gettimeofday (&tv1, 0); } while (tv1.tv_sec < tv2.tv_sec || (tv1.tv_sec == tv2.tv_sec && tv1.tv_usec < tv2.tv_usec)); } void picport::p_out (int b) { struct timeval tv1, tv2; gettimeofday (&tv1, 0); if (tsc_1000ns > 1 && disable_interrupts) asm volatile("pushf; cli"); set_clock_data (1, b); // set data, clock up delay (cable_delay); set_clock_data (0, b); // clock down if (tsc_1000ns > 1 && disable_interrupts) asm volatile("popf"); gettimeofday (&tv2, 0); // We may have spent a long time in an interrupt or in another task // with clock down, so the pic may be pretty drained for power now. // Recharge at least as long as we were without power. long matching_delay = (tv2.tv_sec-tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec; if (matching_delay > 10) // 10 µs should be enough to charge up matching_delay = 10; matching_delay *= 1000; if (matching_delay < cable_delay) matching_delay = cable_delay; delay (matching_delay); } int picport::p_in () { struct timeval tv1, tv2; gettimeofday (&tv1, 0); if (tsc_1000ns > 1 && disable_interrupts) asm volatile("pushf; cli"); set_clock_data (1, 1); // clock up delay (cable_delay); set_clock_data (0, 1); // set data up, clock down if (tsc_1000ns > 1 && disable_interrupts) asm volatile("popf"); gettimeofday (&tv2, 0); // We may have spent a long time in an interrupt or in another task // with clock down, so the pic may be pretty drained for power now. // Recharge at least as long as we were without power. long matching_delay = (tv2.tv_sec-tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec; if (matching_delay > 10) // 10 µs should be enough to charge up matching_delay = 10; matching_delay *= 1000; if (matching_delay < cable_delay) matching_delay = cable_delay; delay (matching_delay); int i; ioctl (fd, TIOCMGET, &i); i = 0 != (i & TIOCM_CTS); if (hardware == k8048) return !i; return i; } int picport::command18 (enum commands18 comm, int data) { int i, shift = comm; if (nop_prog == comm) { // A programming command must leave the last bit clock pulse up p_out (0); p_out (0); p_out (0); set_clock_data (1, 0); // clock up delay (1000*1000); // P9 >1 ms programming time set_clock_data (0, 0); // clock down // P10 >5 µs high voltage discharge time // Later models listed as > 100 µs delay (100*1000); } else { for (i = 0; i < 4; i++) p_out ((shift >> i) & 1); set_clock_data (0, 0); // set data down delay (1000); } shift = 0; // default return value switch (comm) { case nop_erase: // Erase cycle has delay between command and data usleep (10000); // P11 5 ms + P10 5 µs erase time // FALLTHROUGH case instr: case nop_prog: if (0x0e00 == (data & 0xff00)) W[0] = data & 0x00ff; else if (0x6ef8 == data) addr = (addr & 0x00ffff) | (W[0] << 16); else if (0x6ef7 == data) addr = (addr & 0xff00ff) | (W[0] << 8); else if (0x6ef6 == data) addr = (addr & 0xffff00) | W[0]; goto sw; case twrite_dec2: addr -= 2; goto sw; case twrite_inc2: addr += 2; // FALLTHROUGH case twrite: case twrite_prog: sw: for (i = 0; i < 16; i++) p_out ((data >> i) & 1); set_clock_data (0, 0); // set data down break; case tread_dec: --addr; goto sr; case tread_inc: case inc_tread: ++addr; // FALLTHROUGH case shift_out: case tread: sr: for (i = 0; i < 8; i++) p_out(0); delay (1000); for (i = 0; i < 8; i++) shift |= p_in () << i; set_clock_data (0, 0); // set data down } delay (1000); return shift; } int picport::command30 (enum commands30 comm, int data) { int i, shift = comm; for (i = 0; i < 4; i++) p_out ((shift >> i) & 1); shift = 0; // default return value switch (comm) { case SIX: if (0x200000 == (data & 0xff0000)) W[data & 15] = (data & 0x0ffff0) >> 4; else if (0xEB0000 == (data & 0xfff87f)) W[(data >> 7) & 15] = 0; else if (0xBA1830 == (data & 0xfff870)) { // TBLRDL ++W[(data >> 7) & 15]; ++W[data & 15]; } else if (0xBA0830 == (data & 0xfff870)) { // TBLRDL ++W[(data >> 7) & 15]; ++W[data & 15]; } else if (0x880190 == (data & 0xfffff0)) addr = (W[data & 15] << 16) & 0xff0000; addr = (addr & 0xff0000) | W[6]; for (i = 0; i < 24; i++) p_out ((data >> i) & 1); break; case REGOUT: for (i = 0; i < 8; i++) p_out(0); for (i = 0; i < 16; i++) shift |= p_in () << i; } set_clock_data (0, 0); // set data down return shift; } void picport::setaddress (unsigned long a) { if (0 != a && addr == a) return; command18 (instr, 0x0e00 | ((a & 0xff0000) >> 16)); command18 (instr, 0x6ef8); command18 (instr, 0x0e00 | ((a & 0x00ff00) >> 8)); command18 (instr, 0x6ef7); command18 (instr, 0x0e00 | (a & 0x0000ff)); command18 (instr, 0x6ef6); } void picport::setaddress30 (unsigned long a) { if (0 != a && addr == a) return; command30 (SIX, 0x200000 | ((a & 0xff0000) >> 12)); // MOV #, W0 command30 (SIX, 0x880190); // MOV W0, TBLPAG command30 (SIX, 0x200006 | ((a & 0x00ffff) << 4)); // MOV #, W6 } // -1 == error, no programmer present int picport::command (enum commands comm, int data) { int tmp1, tmp2; // first, send out the command, 6 bits int i, shift = comm; for (i = 0; i < 6; i++) p_out ((shift >> i) & 1); set_clock_data (0, 0); // set data down shift = 0; // default return value switch (comm) { case inc_addr: ++addr; if (data != 0) { // 12f508 and 12f509 if (addr >= (unsigned long)(data)) addr = 0; break; } if (addr >= 0x4000) addr = 0x2000; break; case data_from_prog: case data_from_data: delay (1000); tmp1 = p_in (); for (i = 0; i < 14; i++) shift |= p_in () << i; tmp2 = p_in (); set_clock_data (0, 0); // set data down #ifdef CHECK_START_STOP // Start and stop bits must be 1. Most of the old chips at least // conform to this test, but apparently pic12f635 and some other // later chips do not. if (!tmp1 || !tmp2) { cerr << portname << ":PIC programmer missing or chip fault" << endl; return -1; } #endif if (data_from_data == comm) { // Check that the leftover bits were valid, all 1's. // This detects if the programmer is not connected to the port. // Unfortunately later chips clear these bits, so we must // accept both all 1's and all 0's. if ((shift & 0x3f00) != 0x3f00 && (shift & 0x3f00) != 0x0000) { cerr << portname << ": read value " << hex << setfill('0') << setw(4) << shift << dec << ": PIC programmer or chip fault\n" "Is code protection enabled? " "Use --erase option to disable code protection." << endl; return -1; } shift &= 0xff; } break; case load_conf: addr = 0x2000; // FALLTHROUGH case data_for_prog: case data_for_data: delay (1000); p_out (0); for (i = 0; i < 14; i++) p_out ((data >> i) & 1); p_out (0); set_clock_data (0, 0); // set data down break; default: ; } delay (1000); return shift; } picprog-1.9.1/program.cc0000644000076500007650000011316511361223442013605 0ustar jaakkome/* This is a generic program misc functions class v1.0. Copyright 1997,2002,2003,2004,2008,2010 Jaakko Hyvtti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #include #include #include #include #include #include #include #include #include "program.h" using namespace std; program::program () { name = 0; } program::~program () { if (name) delete[] name; } void program::init (char *argv []) { char *p; if (argv && argv [0] && argv [0][0]) { if (name) delete[] name; if ((p = strrchr (argv [0], '/'))) p++; else p = argv [0]; name = new char [strlen (p)+1]; strcpy (name, p); } } const char program::copying_t [] = " GNU GENERAL PUBLIC LICENSE\n\ Version 3, 29 June 2007\n\ \n\ Copyright (C) 2007 Free Software Foundation, Inc. \n\ Everyone is permitted to copy and distribute verbatim copies\n\ of this license document, but changing it is not allowed.\n\ \n\ Preamble\n\ \n\ The GNU General Public License is a free, copyleft license for\n\ software and other kinds of works.\n\ \n\ The licenses for most software and other practical works are designed\n\ to take away your freedom to share and change the works. By contrast,\n\ the GNU General Public License is intended to guarantee your freedom to\n\ share and change all versions of a program--to make sure it remains free\n\ software for all its users. We, the Free Software Foundation, use the\n\ GNU General Public License for most of our software; it applies also to\n\ any other work released this way by its authors. You can apply it to\n\ your programs, too.\n\ \n\ When we speak of free software, we are referring to freedom, not\n\ price. Our General Public Licenses are designed to make sure that you\n\ have the freedom to distribute copies of free software (and charge for\n\ them if you wish), that you receive source code or can get it if you\n\ want it, that you can change the software or use pieces of it in new\n\ free programs, and that you know you can do these things.\n\ \n\ To protect your rights, we need to prevent others from denying you\n\ these rights or asking you to surrender the rights. Therefore, you have\n\ certain responsibilities if you distribute copies of the software, or if\n\ you modify it: responsibilities to respect the freedom of others.\n\ \n\ For example, if you distribute copies of such a program, whether\n\ gratis or for a fee, you must pass on to the recipients the same\n\ freedoms that you received. You must make sure that they, too, receive\n\ or can get the source code. And you must show them these terms so they\n\ know their rights.\n\ \n\ Developers that use the GNU GPL protect your rights with two steps:\n\ (1) assert copyright on the software, and (2) offer you this License\n\ giving you legal permission to copy, distribute and/or modify it.\n\ \n\ For the developers' and authors' protection, the GPL clearly explains\n\ that there is no warranty for this free software. For both users' and\n\ authors' sake, the GPL requires that modified versions be marked as\n\ changed, so that their problems will not be attributed erroneously to\n\ authors of previous versions.\n\ \n\ Some devices are designed to deny users access to install or run\n\ modified versions of the software inside them, although the manufacturer\n\ can do so. This is fundamentally incompatible with the aim of\n\ protecting users' freedom to change the software. The systematic\n\ pattern of such abuse occurs in the area of products for individuals to\n\ use, which is precisely where it is most unacceptable. Therefore, we\n\ have designed this version of the GPL to prohibit the practice for those\n\ products. If such problems arise substantially in other domains, we\n\ stand ready to extend this provision to those domains in future versions\n\ of the GPL, as needed to protect the freedom of users.\n\ \n\ Finally, every program is threatened constantly by software patents.\n\ States should not allow patents to restrict development and use of\n\ software on general-purpose computers, but in those that do, we wish to\n\ avoid the special danger that patents applied to a free program could\n\ make it effectively proprietary. To prevent this, the GPL assures that\n\ patents cannot be used to render the program non-free.\n\ \n\ The precise terms and conditions for copying, distribution and\n\ modification follow.\n\ \n\ TERMS AND CONDITIONS\n\ \n\ 0. Definitions.\n\ \n\ \"This License\" refers to version 3 of the GNU General Public License.\n\ \n\ \"Copyright\" also means copyright-like laws that apply to other kinds of\n\ works, such as semiconductor masks.\n\ \n\ \"The Program\" refers to any copyrightable work licensed under this\n\ License. Each licensee is addressed as \"you\". \"Licensees\" and\n\ \"recipients\" may be individuals or organizations.\n\ \n\ To \"modify\" a work means to copy from or adapt all or part of the work\n\ in a fashion requiring copyright permission, other than the making of an\n\ exact copy. The resulting work is called a \"modified version\" of the\n\ earlier work or a work \"based on\" the earlier work.\n\ \n\ A \"covered work\" means either the unmodified Program or a work based\n\ on the Program.\n\ \n\ To \"propagate\" a work means to do anything with it that, without\n\ permission, would make you directly or secondarily liable for\n\ infringement under applicable copyright law, except executing it on a\n\ computer or modifying a private copy. Propagation includes copying,\n\ distribution (with or without modification), making available to the\n\ public, and in some countries other activities as well.\n\ \n\ To \"convey\" a work means any kind of propagation that enables other\n\ parties to make or receive copies. Mere interaction with a user through\n\ a computer network, with no transfer of a copy, is not conveying.\n\ \n\ An interactive user interface displays \"Appropriate Legal Notices\"\n\ to the extent that it includes a convenient and prominently visible\n\ feature that (1) displays an appropriate copyright notice, and (2)\n\ tells the user that there is no warranty for the work (except to the\n\ extent that warranties are provided), that licensees may convey the\n\ work under this License, and how to view a copy of this License. If\n\ the interface presents a list of user commands or options, such as a\n\ menu, a prominent item in the list meets this criterion.\n\ \n\ 1. Source Code.\n\ \n\ The \"source code\" for a work means the preferred form of the work\n\ for making modifications to it. \"Object code\" means any non-source\n\ form of a work.\n\ \n\ A \"Standard Interface\" means an interface that either is an official\n\ standard defined by a recognized standards body, or, in the case of\n\ interfaces specified for a particular programming language, one that\n\ is widely used among developers working in that language.\n\ \n\ The \"System Libraries\" of an executable work include anything, other\n\ than the work as a whole, that (a) is included in the normal form of\n\ packaging a Major Component, but which is not part of that Major\n\ Component, and (b) serves only to enable use of the work with that\n\ Major Component, or to implement a Standard Interface for which an\n\ implementation is available to the public in source code form. A\n\ \"Major Component\", in this context, means a major essential component\n\ (kernel, window system, and so on) of the specific operating system\n\ (if any) on which the executable work runs, or a compiler used to\n\ produce the work, or an object code interpreter used to run it.\n\ \n\ The \"Corresponding Source\" for a work in object code form means all\n\ the source code needed to generate, install, and (for an executable\n\ work) run the object code and to modify the work, including scripts to\n\ control those activities. However, it does not include the work's\n\ System Libraries, or general-purpose tools or generally available free\n\ programs which are used unmodified in performing those activities but\n\ which are not part of the work. For example, Corresponding Source\n\ includes interface definition files associated with source files for\n\ the work, and the source code for shared libraries and dynamically\n\ linked subprograms that the work is specifically designed to require,\n\ such as by intimate data communication or control flow between those\n\ subprograms and other parts of the work.\n\ \n\ The Corresponding Source need not include anything that users\n\ can regenerate automatically from other parts of the Corresponding\n\ Source.\n\ \n\ The Corresponding Source for a work in source code form is that\n\ same work.\n\ \n\ 2. Basic Permissions.\n\ \n\ All rights granted under this License are granted for the term of\n\ copyright on the Program, and are irrevocable provided the stated\n\ conditions are met. This License explicitly affirms your unlimited\n\ permission to run the unmodified Program. The output from running a\n\ covered work is covered by this License only if the output, given its\n\ content, constitutes a covered work. This License acknowledges your\n\ rights of fair use or other equivalent, as provided by copyright law.\n\ \n\ You may make, run and propagate covered works that you do not\n\ convey, without conditions so long as your license otherwise remains\n\ in force. You may convey covered works to others for the sole purpose\n\ of having them make modifications exclusively for you, or provide you\n\ with facilities for running those works, provided that you comply with\n\ the terms of this License in conveying all material for which you do\n\ not control copyright. Those thus making or running the covered works\n\ for you must do so exclusively on your behalf, under your direction\n\ and control, on terms that prohibit them from making any copies of\n\ your copyrighted material outside their relationship with you.\n\ \n\ Conveying under any other circumstances is permitted solely under\n\ the conditions stated below. Sublicensing is not allowed; section 10\n\ makes it unnecessary.\n\ \n\ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\ \n\ No covered work shall be deemed part of an effective technological\n\ measure under any applicable law fulfilling obligations under article\n\ 11 of the WIPO copyright treaty adopted on 20 December 1996, or\n\ similar laws prohibiting or restricting circumvention of such\n\ measures.\n\ \n\ When you convey a covered work, you waive any legal power to forbid\n\ circumvention of technological measures to the extent such circumvention\n\ is effected by exercising rights under this License with respect to\n\ the covered work, and you disclaim any intention to limit operation or\n\ modification of the work as a means of enforcing, against the work's\n\ users, your or third parties' legal rights to forbid circumvention of\n\ technological measures.\n\ \n\ 4. Conveying Verbatim Copies.\n\ \n\ You may convey verbatim copies of the Program's source code as you\n\ receive it, in any medium, provided that you conspicuously and\n\ appropriately publish on each copy an appropriate copyright notice;\n\ keep intact all notices stating that this License and any\n\ non-permissive terms added in accord with section 7 apply to the code;\n\ keep intact all notices of the absence of any warranty; and give all\n\ recipients a copy of this License along with the Program.\n\ \n\ You may charge any price or no price for each copy that you convey,\n\ and you may offer support or warranty protection for a fee.\n\ \n\ 5. Conveying Modified Source Versions.\n\ \n\ You may convey a work based on the Program, or the modifications to\n\ produce it from the Program, in the form of source code under the\n\ terms of section 4, provided that you also meet all of these conditions:\n\ \n\ a) The work must carry prominent notices stating that you modified\n\ it, and giving a relevant date.\n\ \n\ b) The work must carry prominent notices stating that it is\n\ released under this License and any conditions added under section\n\ 7. This requirement modifies the requirement in section 4 to\n\ \"keep intact all notices\".\n\ \n\ c) You must license the entire work, as a whole, under this\n\ License to anyone who comes into possession of a copy. This\n\ License will therefore apply, along with any applicable section 7\n\ additional terms, to the whole of the work, and all its parts,\n\ regardless of how they are packaged. This License gives no\n\ permission to license the work in any other way, but it does not\n\ invalidate such permission if you have separately received it.\n\ \n\ d) If the work has interactive user interfaces, each must display\n\ Appropriate Legal Notices; however, if the Program has interactive\n\ interfaces that do not display Appropriate Legal Notices, your\n\ work need not make them do so.\n\ \n\ A compilation of a covered work with other separate and independent\n\ works, which are not by their nature extensions of the covered work,\n\ and which are not combined with it such as to form a larger program,\n\ in or on a volume of a storage or distribution medium, is called an\n\ \"aggregate\" if the compilation and its resulting copyright are not\n\ used to limit the access or legal rights of the compilation's users\n\ beyond what the individual works permit. Inclusion of a covered work\n\ in an aggregate does not cause this License to apply to the other\n\ parts of the aggregate.\n\ \n\ 6. Conveying Non-Source Forms.\n\ \n\ You may convey a covered work in object code form under the terms\n\ of sections 4 and 5, provided that you also convey the\n\ machine-readable Corresponding Source under the terms of this License,\n\ in one of these ways:\n\ \n\ a) Convey the object code in, or embodied in, a physical product\n\ (including a physical distribution medium), accompanied by the\n\ Corresponding Source fixed on a durable physical medium\n\ customarily used for software interchange.\n\ \n\ b) Convey the object code in, or embodied in, a physical product\n\ (including a physical distribution medium), accompanied by a\n\ written offer, valid for at least three years and valid for as\n\ long as you offer spare parts or customer support for that product\n\ model, to give anyone who possesses the object code either (1) a\n\ copy of the Corresponding Source for all the software in the\n\ product that is covered by this License, on a durable physical\n\ medium customarily used for software interchange, for a price no\n\ more than your reasonable cost of physically performing this\n\ conveying of source, or (2) access to copy the\n\ Corresponding Source from a network server at no charge.\n\ \n\ c) Convey individual copies of the object code with a copy of the\n\ written offer to provide the Corresponding Source. This\n\ alternative is allowed only occasionally and noncommercially, and\n\ only if you received the object code with such an offer, in accord\n\ with subsection 6b.\n\ \n\ d) Convey the object code by offering access from a designated\n\ place (gratis or for a charge), and offer equivalent access to the\n\ Corresponding Source in the same way through the same place at no\n\ further charge. You need not require recipients to copy the\n\ Corresponding Source along with the object code. If the place to\n\ copy the object code is a network server, the Corresponding Source\n\ may be on a different server (operated by you or a third party)\n\ that supports equivalent copying facilities, provided you maintain\n\ clear directions next to the object code saying where to find the\n\ Corresponding Source. Regardless of what server hosts the\n\ Corresponding Source, you remain obligated to ensure that it is\n\ available for as long as needed to satisfy these requirements.\n\ \n\ e) Convey the object code using peer-to-peer transmission, provided\n\ you inform other peers where the object code and Corresponding\n\ Source of the work are being offered to the general public at no\n\ charge under subsection 6d.\n\ \n\ A separable portion of the object code, whose source code is excluded\n\ from the Corresponding Source as a System Library, need not be\n\ included in conveying the object code work.\n\ \n\ A \"User Product\" is either (1) a \"consumer product\", which means any\n\ tangible personal property which is normally used for personal, family,\n\ or household purposes, or (2) anything designed or sold for incorporation\n\ into a dwelling. In determining whether a product is a consumer product,\n\ doubtful cases shall be resolved in favor of coverage. For a particular\n\ product received by a particular user, \"normally used\" refers to a\n\ typical or common use of that class of product, regardless of the status\n\ of the particular user or of the way in which the particular user\n\ actually uses, or expects or is expected to use, the product. A product\n\ is a consumer product regardless of whether the product has substantial\n\ commercial, industrial or non-consumer uses, unless such uses represent\n\ the only significant mode of use of the product.\n\ \n\ \"Installation Information\" for a User Product means any methods,\n\ procedures, authorization keys, or other information required to install\n\ and execute modified versions of a covered work in that User Product from\n\ a modified version of its Corresponding Source. The information must\n\ suffice to ensure that the continued functioning of the modified object\n\ code is in no case prevented or interfered with solely because\n\ modification has been made.\n\ \n\ If you convey an object code work under this section in, or with, or\n\ specifically for use in, a User Product, and the conveying occurs as\n\ part of a transaction in which the right of possession and use of the\n\ User Product is transferred to the recipient in perpetuity or for a\n\ fixed term (regardless of how the transaction is characterized), the\n\ Corresponding Source conveyed under this section must be accompanied\n\ by the Installation Information. But this requirement does not apply\n\ if neither you nor any third party retains the ability to install\n\ modified object code on the User Product (for example, the work has\n\ been installed in ROM).\n\ \n\ The requirement to provide Installation Information does not include a\n\ requirement to continue to provide support service, warranty, or updates\n\ for a work that has been modified or installed by the recipient, or for\n\ the User Product in which it has been modified or installed. Access to a\n\ network may be denied when the modification itself materially and\n\ adversely affects the operation of the network or violates the rules and\n\ protocols for communication across the network.\n\ \n\ Corresponding Source conveyed, and Installation Information provided,\n\ in accord with this section must be in a format that is publicly\n\ documented (and with an implementation available to the public in\n\ source code form), and must require no special password or key for\n\ unpacking, reading or copying.\n\ \n\ 7. Additional Terms.\n\ \n\ \"Additional permissions\" are terms that supplement the terms of this\n\ License by making exceptions from one or more of its conditions.\n\ Additional permissions that are applicable to the entire Program shall\n\ be treated as though they were included in this License, to the extent\n\ that they are valid under applicable law. If additional permissions\n\ apply only to part of the Program, that part may be used separately\n\ under those permissions, but the entire Program remains governed by\n\ this License without regard to the additional permissions.\n\ \n\ When you convey a copy of a covered work, you may at your option\n\ remove any additional permissions from that copy, or from any part of\n\ it. (Additional permissions may be written to require their own\n\ removal in certain cases when you modify the work.) You may place\n\ additional permissions on material, added by you to a covered work,\n\ for which you have or can give appropriate copyright permission.\n\ \n\ Notwithstanding any other provision of this License, for material you\n\ add to a covered work, you may (if authorized by the copyright holders of\n\ that material) supplement the terms of this License with terms:\n\ \n\ a) Disclaiming warranty or limiting liability differently from the\n\ terms of sections 15 and 16 of this License; or\n\ \n\ b) Requiring preservation of specified reasonable legal notices or\n\ author attributions in that material or in the Appropriate Legal\n\ Notices displayed by works containing it; or\n\ \n\ c) Prohibiting misrepresentation of the origin of that material, or\n\ requiring that modified versions of such material be marked in\n\ reasonable ways as different from the original version; or\n\ \n\ d) Limiting the use for publicity purposes of names of licensors or\n\ authors of the material; or\n\ \n\ e) Declining to grant rights under trademark law for use of some\n\ trade names, trademarks, or service marks; or\n\ \n\ f) Requiring indemnification of licensors and authors of that\n\ material by anyone who conveys the material (or modified versions of\n\ it) with contractual assumptions of liability to the recipient, for\n\ any liability that these contractual assumptions directly impose on\n\ those licensors and authors.\n\ \n\ All other non-permissive additional terms are considered \"further\n\ restrictions\" within the meaning of section 10. If the Program as you\n\ received it, or any part of it, contains a notice stating that it is\n\ governed by this License along with a term that is a further\n\ restriction, you may remove that term. If a license document contains\n\ a further restriction but permits relicensing or conveying under this\n\ License, you may add to a covered work material governed by the terms\n\ of that license document, provided that the further restriction does\n\ not survive such relicensing or conveying.\n\ \n\ If you add terms to a covered work in accord with this section, you\n\ must place, in the relevant source files, a statement of the\n\ additional terms that apply to those files, or a notice indicating\n\ where to find the applicable terms.\n\ \n\ Additional terms, permissive or non-permissive, may be stated in the\n\ form of a separately written license, or stated as exceptions;\n\ the above requirements apply either way.\n\ \n\ 8. Termination.\n\ \n\ You may not propagate or modify a covered work except as expressly\n\ provided under this License. Any attempt otherwise to propagate or\n\ modify it is void, and will automatically terminate your rights under\n\ this License (including any patent licenses granted under the third\n\ paragraph of section 11).\n\ \n\ However, if you cease all violation of this License, then your\n\ license from a particular copyright holder is reinstated (a)\n\ provisionally, unless and until the copyright holder explicitly and\n\ finally terminates your license, and (b) permanently, if the copyright\n\ holder fails to notify you of the violation by some reasonable means\n\ prior to 60 days after the cessation.\n\ \n\ Moreover, your license from a particular copyright holder is\n\ reinstated permanently if the copyright holder notifies you of the\n\ violation by some reasonable means, this is the first time you have\n\ received notice of violation of this License (for any work) from that\n\ copyright holder, and you cure the violation prior to 30 days after\n\ your receipt of the notice.\n\ \n\ Termination of your rights under this section does not terminate the\n\ licenses of parties who have received copies or rights from you under\n\ this License. If your rights have been terminated and not permanently\n\ reinstated, you do not qualify to receive new licenses for the same\n\ material under section 10.\n\ \n\ 9. Acceptance Not Required for Having Copies.\n\ \n\ You are not required to accept this License in order to receive or\n\ run a copy of the Program. Ancillary propagation of a covered work\n\ occurring solely as a consequence of using peer-to-peer transmission\n\ to receive a copy likewise does not require acceptance. However,\n\ nothing other than this License grants you permission to propagate or\n\ modify any covered work. These actions infringe copyright if you do\n\ not accept this License. Therefore, by modifying or propagating a\n\ covered work, you indicate your acceptance of this License to do so.\n\ \n\ 10. Automatic Licensing of Downstream Recipients.\n\ \n\ Each time you convey a covered work, the recipient automatically\n\ receives a license from the original licensors, to run, modify and\n\ propagate that work, subject to this License. You are not responsible\n\ for enforcing compliance by third parties with this License.\n\ \n\ An \"entity transaction\" is a transaction transferring control of an\n\ organization, or substantially all assets of one, or subdividing an\n\ organization, or merging organizations. If propagation of a covered\n\ work results from an entity transaction, each party to that\n\ transaction who receives a copy of the work also receives whatever\n\ licenses to the work the party's predecessor in interest had or could\n\ give under the previous paragraph, plus a right to possession of the\n\ Corresponding Source of the work from the predecessor in interest, if\n\ the predecessor has it or can get it with reasonable efforts.\n\ \n\ You may not impose any further restrictions on the exercise of the\n\ rights granted or affirmed under this License. For example, you may\n\ not impose a license fee, royalty, or other charge for exercise of\n\ rights granted under this License, and you may not initiate litigation\n\ (including a cross-claim or counterclaim in a lawsuit) alleging that\n\ any patent claim is infringed by making, using, selling, offering for\n\ sale, or importing the Program or any portion of it.\n\ \n\ 11. Patents.\n\ \n\ A \"contributor\" is a copyright holder who authorizes use under this\n\ License of the Program or a work on which the Program is based. The\n\ work thus licensed is called the contributor's \"contributor version\".\n\ \n\ A contributor's \"essential patent claims\" are all patent claims\n\ owned or controlled by the contributor, whether already acquired or\n\ hereafter acquired, that would be infringed by some manner, permitted\n\ by this License, of making, using, or selling its contributor version,\n\ but do not include claims that would be infringed only as a\n\ consequence of further modification of the contributor version. For\n\ purposes of this definition, \"control\" includes the right to grant\n\ patent sublicenses in a manner consistent with the requirements of\n\ this License.\n\ \n\ Each contributor grants you a non-exclusive, worldwide, royalty-free\n\ patent license under the contributor's essential patent claims, to\n\ make, use, sell, offer for sale, import and otherwise run, modify and\n\ propagate the contents of its contributor version.\n\ \n\ In the following three paragraphs, a \"patent license\" is any express\n\ agreement or commitment, however denominated, not to enforce a patent\n\ (such as an express permission to practice a patent or covenant not to\n\ sue for patent infringement). To \"grant\" such a patent license to a\n\ party means to make such an agreement or commitment not to enforce a\n\ patent against the party.\n\ \n\ If you convey a covered work, knowingly relying on a patent license,\n\ and the Corresponding Source of the work is not available for anyone\n\ to copy, free of charge and under the terms of this License, through a\n\ publicly available network server or other readily accessible means,\n\ then you must either (1) cause the Corresponding Source to be so\n\ available, or (2) arrange to deprive yourself of the benefit of the\n\ patent license for this particular work, or (3) arrange, in a manner\n\ consistent with the requirements of this License, to extend the patent\n\ license to downstream recipients. \"Knowingly relying\" means you have\n\ actual knowledge that, but for the patent license, your conveying the\n\ covered work in a country, or your recipient's use of the covered work\n\ in a country, would infringe one or more identifiable patents in that\n\ country that you have reason to believe are valid.\n\ \n\ If, pursuant to or in connection with a single transaction or\n\ arrangement, you convey, or propagate by procuring conveyance of, a\n\ covered work, and grant a patent license to some of the parties\n\ receiving the covered work authorizing them to use, propagate, modify\n\ or convey a specific copy of the covered work, then the patent license\n\ you grant is automatically extended to all recipients of the covered\n\ work and works based on it.\n\ \n\ A patent license is \"discriminatory\" if it does not include within\n\ the scope of its coverage, prohibits the exercise of, or is\n\ conditioned on the non-exercise of one or more of the rights that are\n\ specifically granted under this License. You may not convey a covered\n\ work if you are a party to an arrangement with a third party that is\n\ in the business of distributing software, under which you make payment\n\ to the third party based on the extent of your activity of conveying\n\ the work, and under which the third party grants, to any of the\n\ parties who would receive the covered work from you, a discriminatory\n\ patent license (a) in connection with copies of the covered work\n\ conveyed by you (or copies made from those copies), or (b) primarily\n\ for and in connection with specific products or compilations that\n\ contain the covered work, unless you entered into that arrangement,\n\ or that patent license was granted, prior to 28 March 2007.\n\ \n\ Nothing in this License shall be construed as excluding or limiting\n\ any implied license or other defenses to infringement that may\n\ otherwise be available to you under applicable patent law.\n\ \n\ 12. No Surrender of Others' Freedom.\n\ \n\ If conditions are imposed on you (whether by court order, agreement or\n\ otherwise) that contradict the conditions of this License, they do not\n\ excuse you from the conditions of this License. If you cannot convey a\n\ covered work so as to satisfy simultaneously your obligations under this\n\ License and any other pertinent obligations, then as a consequence you may\n\ not convey it at all. For example, if you agree to terms that obligate you\n\ to collect a royalty for further conveying from those to whom you convey\n\ the Program, the only way you could satisfy both those terms and this\n\ License would be to refrain entirely from conveying the Program.\n\ \n\ 13. Use with the GNU Affero General Public License.\n\ \n\ Notwithstanding any other provision of this License, you have\n\ permission to link or combine any covered work with a work licensed\n\ under version 3 of the GNU Affero General Public License into a single\n\ combined work, and to convey the resulting work. The terms of this\n\ License will continue to apply to the part which is the covered work,\n\ but the special requirements of the GNU Affero General Public License,\n\ section 13, concerning interaction through a network will apply to the\n\ combination as such.\n\ \n\ 14. Revised Versions of this License.\n\ \n\ The Free Software Foundation may publish revised and/or new versions of\n\ the GNU General Public License from time to time. Such new versions will\n\ be similar in spirit to the present version, but may differ in detail to\n\ address new problems or concerns.\n\ \n\ Each version is given a distinguishing version number. If the\n\ Program specifies that a certain numbered version of the GNU General\n\ Public License \"or any later version\" applies to it, you have the\n\ option of following the terms and conditions either of that numbered\n\ version or of any later version published by the Free Software\n\ Foundation. If the Program does not specify a version number of the\n\ GNU General Public License, you may choose any version ever published\n\ by the Free Software Foundation.\n\ \n\ If the Program specifies that a proxy can decide which future\n\ versions of the GNU General Public License can be used, that proxy's\n\ public statement of acceptance of a version permanently authorizes you\n\ to choose that version for the Program.\n\ \n\ Later license versions may give you additional or different\n\ permissions. However, no additional obligations are imposed on any\n\ author or copyright holder as a result of your choosing to follow a\n\ later version.\n\ "; const char program::warranty_t [] = " 15. Disclaimer of Warranty.\n\ \n\ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n\ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\n\ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\n\ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\n\ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n\ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\n\ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\n\ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\ \n\ 16. Limitation of Liability.\n\ \n\ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\n\ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\n\ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\n\ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\n\ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n\ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\n\ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\n\ SUCH DAMAGES.\n\ \n\ 17. Interpretation of Sections 15 and 16.\n\ \n\ If the disclaimer of warranty and limitation of liability provided\n\ above cannot be given local legal effect according to their terms,\n\ reviewing courts shall apply local law that most closely approximates\n\ an absolute waiver of all civil liability in connection with the\n\ Program, unless a warranty or assumption of liability accompanies a\n\ copy of the Program in return for a fee.\n\ "; static void simple_pager (const char *t) { struct winsize w; char c; if (!isatty (1) || 0 > ioctl (1, TIOCGWINSZ, &w) || w.ws_row < 2 || w.ws_col < 76) { cout << t; return; } int lines = 0; const char *start = t; const char *end = t; while ((end = strchr (end, '\n')) && *++end) { if (++lines >= w.ws_row-1) { cout << string (start, end-start); lines = 0; start = end; cout << "Press enter to continue" << flush; while (cin.get(c) && '\n' != c) ; } } if (*start) cout << start; // Print the last page. } void program::warranty () { simple_pager (program::warranty_t); } void program::copying () { simple_pager (program::copying_t); } static void wrapif (int& column, int cols, int wid) { if (cols < (column += wid)) { cerr << endl; column = wid; } } void program::usage (struct option *long_opts, char *short_opts) { struct option *op; string charops; char *short_set = strdup (short_opts); char *tmp_set; struct winsize w; int column; if (!isatty (1) || 0 > ioctl (1, TIOCGWINSZ, &w) || w.ws_col < 40) w.ws_col = 80; cerr << "Usage: " << name; column = 7 + strlen (name); for (op = long_opts; op->name; op++) { if (!op->flag && (tmp_set = strchr (short_set, op->val))) *tmp_set = ' '; switch (op->has_arg) { case required_argument: wrapif (column, w.ws_col, 5 + strlen (op->name) + 6); cerr << " [ --" << op->name << "=arg ]"; if (!op->flag) { wrapif (column, w.ws_col, 11); cerr << " [ -" << (char)op->val << " arg ]"; } break; case optional_argument: wrapif (column, w.ws_col, 5 + strlen (op->name) + 9); cerr << " [ --" << op->name << "[=arg ] ]"; if (!op->flag) { wrapif (column, w.ws_col, 15); cerr << " [ -" << (char)op->val << " [ arg ] ]"; } break; default: wrapif (column, w.ws_col, 5 + strlen (op->name) + 2); cerr << " [ --" << op->name << " ]"; if (!op->flag) charops += op->val; } } for (tmp_set = short_set; *tmp_set; tmp_set++) { if (' ' != *tmp_set && ':' != *tmp_set) { if (':' == tmp_set [1]) { wrapif (column, w.ws_col, 12); cerr << " [ -" << *tmp_set++ << " arg ]"; } else charops += *tmp_set; } } if (charops.length ()) { wrapif (column, w.ws_col, 4 + charops.length () + 2); cerr << " [ -" << charops << " ]"; } cerr << endl; exit (EX_USAGE); } picprog-1.9.1/testport.cc0000644000076500007650000001176111361213341014016 0ustar jaakkome/* -*- c++ -*- This is Testport, simple serial port testing program. Copyright © 2007,2010 Jaakko Hyvätti This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . The author may be contacted at: Email: Jaakko.Hyvatti@iki.fi URL: http://www.iki.fi/hyvatti/ Phone: +358 40 5011222 Please send any suggestions, bug reports, success stories etc. to the Email address above. Include word 'picprog' in the subject line to make sure your email passes my spam filtering. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif int modem_signals[] = { TIOCM_CD, TIOCM_RI, TIOCM_CTS, TIOCM_DSR, TIOCM_RTS, TIOCM_DTR }; const char * modem_signal_names[] = { "CD", "RI", "CTS", "DSR", "RTS", "DTR" }; const int num_signals = sizeof(modem_signals) / sizeof(modem_signals[0]); int main (int argc, char **argv) { int fd; struct termios saved, termstate, ttysaved, ttystate; int modembits; const char *portname; bool break_on = false; int signal_mask = 0; for (int s = 0; s < num_signals; ++s) signal_mask |= modem_signals[s]; if (argc != 2) { cerr << "Usage: " << argv[0] << " /dev/ttyS0" << endl; exit (1); } portname = argv[1]; cout << "Keys:" << endl << "q\tquit" << endl << "b\ttoggle break" << endl << "r\ttoggle rts" << endl << "d\ttoggle dtr" << endl << "\tother keys transmit that char." << endl ; if (0 > (fd = open (portname, O_RDWR|O_NOCTTY|O_NONBLOCK))) { int e = errno; cerr << "Unable to open tty " << portname << ":" << strerror (e) << endl; exit (EX_IOERR); } tcgetattr (fd, &saved); termstate = saved; termstate.c_iflag = IGNBRK | IGNPAR; termstate.c_oflag = 0; termstate.c_cflag = B9600 | CS8 | CREAD | CLOCAL; termstate.c_lflag = 0; termstate.c_cc[VMIN] = 0; termstate.c_cc[VTIME] = 0; tcsetattr (fd, TCSANOW, &termstate); ioctl (fd, TIOCMGET, &modembits); if (isatty (0)) { tcgetattr (0, &ttysaved); ttystate = ttysaved; ttystate.c_iflag = IGNBRK | IGNPAR; ttystate.c_oflag = OPOST | ONLCR; ttystate.c_cflag = B9600 | CS8 | CREAD | CLOCAL; ttystate.c_lflag = 0; ttystate.c_cc[VMIN] = 0; ttystate.c_cc[VTIME] = 0; tcsetattr (0, TCSANOW, &ttystate); cout << "Terminal set up." << endl; } for (;;) { int n; char instr[2]; n = read (0, instr, 1); if (n < 0) { int e = errno; cerr << "Read error on tty " << strerror (e) << endl; break; } if (n == 1) { if (instr[0] == 'q' || instr[0] == 3) break; if (instr[0] == 'b') { break_on = !break_on; if (0 > ioctl (fd, break_on ? TIOCSBRK : TIOCCBRK, 0)) { int e = errno; cerr << "Unable to set break on tty " << portname << ":" << strerror (e) << endl; break; } continue; } if (instr[0] == 'r') { int newmodem = modembits; newmodem ^= TIOCM_RTS; ioctl (fd, TIOCMSET, &newmodem); continue; } if (instr[0] == 'd') { int newmodem = modembits; newmodem ^= TIOCM_DTR; ioctl (fd, TIOCMSET, &newmodem); continue; } cout << "OUT: 0x" << hex << int(instr[0]) << dec << endl; if (1 != write (fd, instr, 1)) { cerr << "Write err" << strerror(errno) << endl; break; } continue; } // read 1 char from keyboard n = read (fd, instr, 1); if (n < 0) { int e = errno; cerr << "Read error on serial port " << strerror (e) << endl; break; } if (n == 1) { cout << "IN: 0x" << hex << int(instr[0]) << dec << endl; } int newmodem; ioctl (fd, TIOCMGET, &newmodem); if ((newmodem & signal_mask) != (modembits & signal_mask)) { string message; for (int s = 0; s < num_signals; ++s) { string sstate = ((newmodem & modem_signals[s]) ? string("+") : string("-")) + string(modem_signal_names[s]); cout << sstate << ' '; if ((newmodem & modem_signals[s]) != (modembits & modem_signals[s])) { message += " " + sstate; } } cout << ':' << message << endl; modembits = newmodem; } } // for ever; if (isatty (0)) { tcsetattr (0, TCSANOW, &ttysaved); } tcsetattr (fd, TCSANOW, &saved); close (fd); cout << "Quit." << endl; return 0; }