From c184ee0e1eda1b1bed596428374f6185ff42d895 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Sat, 27 Aug 2011 21:27:19 +0000 Subject: [PATCH] This is release 5.11. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/tags/RELEASE_5_11_0@999 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrdude/.cvsignore | 33 + avrdude/AUTHORS | 26 + avrdude/BUILD-FROM-SVN | 13 + avrdude/COPYING | 340 + avrdude/ChangeLog | 272 + avrdude/ChangeLog-2001 | 598 + avrdude/ChangeLog-2002 | 237 + avrdude/ChangeLog-2003 | 1095 ++ avrdude/ChangeLog-2004-2006 | 1644 +++ avrdude/ChangeLog-2007 | 364 + avrdude/ChangeLog-2008 | 185 + avrdude/ChangeLog-2009 | 411 + avrdude/ChangeLog-2010 | 354 + avrdude/Makefile.am | 179 + avrdude/NEWS | 572 + avrdude/README | 6 + avrdude/arduino.c | 131 + avrdude/arduino.h | 29 + avrdude/avr.c | 1031 ++ avrdude/avr.h | 77 + avrdude/avr910.c | 798 ++ avrdude/avr910.h | 37 + avrdude/avrdude.1 | 1086 ++ avrdude/avrdude.conf.in | 16921 +++++++++++++++++++++++++ avrdude/avrdude.h | 56 + avrdude/avrdude.spec.in | 113 + avrdude/avrftdi.c | 1079 ++ avrdude/avrftdi.h | 56 + avrdude/avrpart.c | 547 + avrdude/avrpart.h | 225 + avrdude/bitbang.c | 660 + avrdude/bitbang.h | 59 + avrdude/bootstrap | 19 + avrdude/buspirate.c | 795 ++ avrdude/buspirate.h | 30 + avrdude/butterfly.c | 747 ++ avrdude/butterfly.h | 36 + avrdude/config.c | 307 + avrdude/config.h | 109 + avrdude/config_gram.y | 1600 +++ avrdude/configure.ac | 385 + avrdude/confwin.c | 54 + avrdude/confwin.h | 40 + avrdude/crc16.c | 83 + avrdude/crc16.h | 34 + avrdude/doc/.cvsignore | 22 + avrdude/doc/Makefile.am | 60 + avrdude/doc/TODO | 26 + avrdude/doc/avrdude.texi | 2567 ++++ avrdude/fileio.c | 1159 ++ avrdude/fileio.h | 65 + avrdude/freebsd_ppi.h | 40 + avrdude/jtagmkI.c | 1404 ++ avrdude/jtagmkI.h | 36 + avrdude/jtagmkII.c | 3797 ++++++ avrdude/jtagmkII.h | 57 + avrdude/jtagmkII_private.h | 363 + avrdude/jtagmkI_private.h | 169 + avrdude/lexer.l | 291 + avrdude/linux_ppdev.h | 57 + avrdude/lists.c | 1371 ++ avrdude/lists.h | 115 + avrdude/main.c | 1269 ++ avrdude/my_ddk_hidsdi.h | 49 + avrdude/par.c | 462 + avrdude/par.h | 35 + avrdude/pgm.c | 228 + avrdude/pgm.h | 145 + avrdude/pindefs.h | 44 + avrdude/ppi.c | 238 + avrdude/ppi.h | 60 + avrdude/ppiwin.c | 418 + avrdude/safemode.c | 363 + avrdude/safemode.h | 47 + avrdude/ser_avrdoper.c | 659 + avrdude/ser_posix.c | 503 + avrdude/ser_win32.c | 408 + avrdude/serbb.h | 37 + avrdude/serbb_posix.c | 313 + avrdude/serbb_win32.c | 374 + avrdude/serial.h | 77 + avrdude/solaris_ecpp.h | 51 + avrdude/stk500.c | 1364 ++ avrdude/stk500.h | 41 + avrdude/stk500_private.h | 103 + avrdude/stk500generic.c | 91 + avrdude/stk500generic.h | 29 + avrdude/stk500v2.c | 3926 ++++++ avrdude/stk500v2.h | 52 + avrdude/stk500v2_private.h | 322 + avrdude/term.c | 940 ++ avrdude/term.h | 39 + avrdude/tools/get-dw-params.xsl | 156 + avrdude/tools/get-hv-params.xsl | 255 + avrdude/tools/get-stk600-cards.xsl | 63 + avrdude/tools/get-stk600-devices.xsl | 52 + avrdude/tpi.h | 72 + avrdude/update.c | 372 + avrdude/update.h | 55 + avrdude/usb_libusb.c | 483 + avrdude/usbasp.c | 1131 ++ avrdude/usbasp.h | 149 + avrdude/usbdevs.h | 43 + avrdude/usbtiny.c | 581 + avrdude/usbtiny.h | 76 + avrdude/windows/.cvsignore | 4 + avrdude/windows/Makefile.am | 58 + avrdude/windows/giveio.c | 168 + avrdude/windows/giveio.sys | Bin 0 -> 5248 bytes avrdude/windows/install_giveio.bat | 34 + avrdude/windows/loaddrv.c | 460 + avrdude/windows/loaddrv.h | 20 + avrdude/windows/remove_giveio.bat | 14 + avrdude/windows/status_giveio.bat | 12 + avrdude/wiring.c | 236 + avrdude/wiring.h | 29 + 116 files changed, 62282 insertions(+) create mode 100644 avrdude/.cvsignore create mode 100644 avrdude/AUTHORS create mode 100644 avrdude/BUILD-FROM-SVN create mode 100644 avrdude/COPYING create mode 100644 avrdude/ChangeLog create mode 100644 avrdude/ChangeLog-2001 create mode 100644 avrdude/ChangeLog-2002 create mode 100644 avrdude/ChangeLog-2003 create mode 100644 avrdude/ChangeLog-2004-2006 create mode 100644 avrdude/ChangeLog-2007 create mode 100644 avrdude/ChangeLog-2008 create mode 100644 avrdude/ChangeLog-2009 create mode 100644 avrdude/ChangeLog-2010 create mode 100644 avrdude/Makefile.am create mode 100644 avrdude/NEWS create mode 100644 avrdude/README create mode 100644 avrdude/arduino.c create mode 100644 avrdude/arduino.h create mode 100644 avrdude/avr.c create mode 100644 avrdude/avr.h create mode 100644 avrdude/avr910.c create mode 100644 avrdude/avr910.h create mode 100644 avrdude/avrdude.1 create mode 100644 avrdude/avrdude.conf.in create mode 100644 avrdude/avrdude.h create mode 100644 avrdude/avrdude.spec.in create mode 100644 avrdude/avrftdi.c create mode 100644 avrdude/avrftdi.h create mode 100644 avrdude/avrpart.c create mode 100644 avrdude/avrpart.h create mode 100644 avrdude/bitbang.c create mode 100644 avrdude/bitbang.h create mode 100755 avrdude/bootstrap create mode 100644 avrdude/buspirate.c create mode 100644 avrdude/buspirate.h create mode 100644 avrdude/butterfly.c create mode 100644 avrdude/butterfly.h create mode 100644 avrdude/config.c create mode 100644 avrdude/config.h create mode 100644 avrdude/config_gram.y create mode 100644 avrdude/configure.ac create mode 100644 avrdude/confwin.c create mode 100644 avrdude/confwin.h create mode 100644 avrdude/crc16.c create mode 100644 avrdude/crc16.h create mode 100644 avrdude/doc/.cvsignore create mode 100644 avrdude/doc/Makefile.am create mode 100644 avrdude/doc/TODO create mode 100644 avrdude/doc/avrdude.texi create mode 100644 avrdude/fileio.c create mode 100644 avrdude/fileio.h create mode 100644 avrdude/freebsd_ppi.h create mode 100644 avrdude/jtagmkI.c create mode 100644 avrdude/jtagmkI.h create mode 100644 avrdude/jtagmkII.c create mode 100644 avrdude/jtagmkII.h create mode 100644 avrdude/jtagmkII_private.h create mode 100644 avrdude/jtagmkI_private.h create mode 100644 avrdude/lexer.l create mode 100644 avrdude/linux_ppdev.h create mode 100644 avrdude/lists.c create mode 100644 avrdude/lists.h create mode 100644 avrdude/main.c create mode 100644 avrdude/my_ddk_hidsdi.h create mode 100644 avrdude/par.c create mode 100644 avrdude/par.h create mode 100644 avrdude/pgm.c create mode 100644 avrdude/pgm.h create mode 100644 avrdude/pindefs.h create mode 100644 avrdude/ppi.c create mode 100644 avrdude/ppi.h create mode 100644 avrdude/ppiwin.c create mode 100644 avrdude/safemode.c create mode 100644 avrdude/safemode.h create mode 100644 avrdude/ser_avrdoper.c create mode 100644 avrdude/ser_posix.c create mode 100644 avrdude/ser_win32.c create mode 100644 avrdude/serbb.h create mode 100644 avrdude/serbb_posix.c create mode 100644 avrdude/serbb_win32.c create mode 100644 avrdude/serial.h create mode 100644 avrdude/solaris_ecpp.h create mode 100644 avrdude/stk500.c create mode 100644 avrdude/stk500.h create mode 100644 avrdude/stk500_private.h create mode 100644 avrdude/stk500generic.c create mode 100644 avrdude/stk500generic.h create mode 100644 avrdude/stk500v2.c create mode 100644 avrdude/stk500v2.h create mode 100644 avrdude/stk500v2_private.h create mode 100644 avrdude/term.c create mode 100644 avrdude/term.h create mode 100644 avrdude/tools/get-dw-params.xsl create mode 100644 avrdude/tools/get-hv-params.xsl create mode 100644 avrdude/tools/get-stk600-cards.xsl create mode 100644 avrdude/tools/get-stk600-devices.xsl create mode 100644 avrdude/tpi.h create mode 100644 avrdude/update.c create mode 100644 avrdude/update.h create mode 100644 avrdude/usb_libusb.c create mode 100644 avrdude/usbasp.c create mode 100644 avrdude/usbasp.h create mode 100644 avrdude/usbdevs.h create mode 100644 avrdude/usbtiny.c create mode 100644 avrdude/usbtiny.h create mode 100644 avrdude/windows/.cvsignore create mode 100644 avrdude/windows/Makefile.am create mode 100644 avrdude/windows/giveio.c create mode 100644 avrdude/windows/giveio.sys create mode 100755 avrdude/windows/install_giveio.bat create mode 100644 avrdude/windows/loaddrv.c create mode 100644 avrdude/windows/loaddrv.h create mode 100755 avrdude/windows/remove_giveio.bat create mode 100755 avrdude/windows/status_giveio.bat create mode 100644 avrdude/wiring.c create mode 100644 avrdude/wiring.h diff --git a/avrdude/.cvsignore b/avrdude/.cvsignore new file mode 100644 index 00000000..059edf8b --- /dev/null +++ b/avrdude/.cvsignore @@ -0,0 +1,33 @@ +*.diff +*.patch +y.output +y.tab.h +lexer.c +config_gram.c +config_gram.h +.cvsignore +.depend +.deps +INSTALL +Makefile.in +Makefile +ac_cfg.h.in +aclocal.m4 +autom4te.cache +configure +depcomp +install-sh +compile +missing +mkinstalldirs +stamp-h.in +stamp-h1 +ac_cfg.h +avrdude.conf +avrdude.conf.tmp +avrdude.spec +config.guess +config.log +config.status +config.sub +avrdude diff --git a/avrdude/AUTHORS b/avrdude/AUTHORS new file mode 100644 index 00000000..9996bfb5 --- /dev/null +++ b/avrdude/AUTHORS @@ -0,0 +1,26 @@ +AVRDUDE was written by: + + Brian S. Dean + +Contributors: + + Joerg Wunsch + Eric Weddington + Jan-Hinnerk Reichert + Alex Shepherd + Martin Thomas + Theodore A. Roth + Michael Holzt + Colin O'Flynn + Thomas Fischl + David Hoerl + Michal Ludvig + Darell Tan + Wolfgang Moser + Ville Voipio + Hannes Weisbach + Doug Springer + Brett Hagman + +For minor contributions, please see the ChangeLog files. + diff --git a/avrdude/BUILD-FROM-SVN b/avrdude/BUILD-FROM-SVN new file mode 100644 index 00000000..3a218f2d --- /dev/null +++ b/avrdude/BUILD-FROM-SVN @@ -0,0 +1,13 @@ +$Id$ + +How to build avrdude from SVN: + +1. svn co svn://svn.savannah.nongnu.org/avrdude/trunk + +2. cd trunk/avrdude + +3. ./bootstrap + +4. ./configure + +5. make diff --git a/avrdude/COPYING b/avrdude/COPYING new file mode 100644 index 00000000..d60c31a9 --- /dev/null +++ b/avrdude/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog new file mode 100644 index 00000000..d6a2bcb1 --- /dev/null +++ b/avrdude/ChangeLog @@ -0,0 +1,272 @@ +2011-08-27 Joerg Wunsch + + * configure.ac: Bump version for releasing AVRDUDE 5.11. + +2011-08-26 Joerg Wunsch + + * avrdude.1: Update the list of supported AVR devices. + * doc/avrdude.texi: (Ditto). + +2011-08-26 Joerg Wunsch + + * configure.ac: add -lusb as "other libraries" when checking + for libftdi. + +2011-08-26 Joerg Wunsch + + Submitted by Juergen Weigert: + patch #7056: adding support for mikrokopter bootloader to butterfly + * butterfly.c: Add some specific logic to handle the + mikrokopter.de butterfly bootloader. + * butterfly.h: Add one related function declaration. + * config_gram.y: Add butterfly_mk keyword. + * lexer.l: (Ditto.) + * avrdude.conf.in: Add entry for butterfly_mk. + +2011-08-26 Joerg Wunsch + + Submitted by Stefan Tomanek: + patch #7542: add default_bitclock to configuration files + * config.c: Add the new keyword and its handling. + * config.h: (Ditto.) + * config_gram.y: (Ditto.) + * avrdude.conf.in: (Ditto.) + * main.c: (Ditto.) + * lexer.l: (Ditto.) + * avrdude.1: Document the change. + * doc/avrdude.texi: (Ditto.) + +2011-08-26 Joerg Wunsch + + Submitted by Brett Hagman: + patch #7603: wiring - programmer type for Wiring boards + (based on STK500v2) + * wiring.c: New file. + * wiring.h: (Ditto.) + * Makefile.am: Add new files. + * stk500v2_private.h: Reorganize so some functions and struct + pdata are globally known. + * stk500v2.c: (Ditto.) + * stk500v2.h: (Ditto.) + * lexer.l: Add new programmer keywords. + * config_gram.y: (Ditto.) + * avrdude.conf.in: Add "wiring" programmer entry. + * avrdude.1: Document the new programmer. + * doc/avrdude.texi: (Ditto.) + * AUTHORS: Add Brett Hagman. + +2011-08-26 Joerg Wunsch + + Submitted by an anonymous contributor on the mailinglist: + * avrdude.conf (jtagkey): Add a definition for the Amontec + JTAGKey + +2011-08-26 Joerg Wunsch + + Submitted by Juergen Weigert: + bug #22720: avrdude-5.5 ignores buff settings in avrdude.conf + (Note that the actual bug the subject is about has been fixed + long ago.) + * update.c (do_op): fix a diagnostic message + * pgm.h: add exit_datahigh field + * par.c: set and act upon the exit_datahigh field + * avrdude.1: document the new -E options + * doc/avrdude.texi: (Ditto.) + +2011-08-26 Joerg Wunsch + + bug #33811: Parallel make fails + * Makefile.am (BUILT_SOURCES): Add this macro. + +2011-08-26 Joerg Wunsch + + bug #33114: Segfault after setting the DWEN fuse with Dragon + * jtagII.c (jtagmkII_getsync): Instead of exit()ing from + deep within the tree when detecting the "need debugWIRE" + situation, properly pass this up as a return code. + * jtagII_private.h (JTAGII_GETSYNC_FAIL_GRACEFUL): New constant. + * stk500v2.c (stk500v2_jtagmkII_open): Don't tell anything + anymore when receiving a JTAGII_GETSYNC_FAIL_GRACEFUL from + jtagmkII_getsync(); silently give up (all necessary has been + said already). + +2011-08-26 Joerg Wunsch + + Reported by Jason Hecker: + * usbasp.c (libusb_to_errno): Conditionalize some error codes + that apparently are lacking on MinGW. + +2011-08-25 Joerg Wunsch + + Fix warnings. + * ser_avrdoper.c: add so exit() is declared. + * usbtiny.c (usbtiny_open): provide an initializer to a + "may be used uninitialized" variable (since GCC could not + fully detect the logic behind). + +2011-08-25 Joerg Wunsch + + * configure.ac: Add a check for FreeBSD's libusb-1.0 + compatible library that is found in libusb.a/.so on + FreeBSD 8+. + +2011-08-25 Joerg Wunsch + + Submitted by Doug Springer, based on work by + Wolfgang Moser, Ville Voipio, Hannes Weisbach + patch #7486: Patch to add FT2232C/D, FT2232H, FT4232H, + usbvid, usbpid, usbdev for USB support - Based on #7062 + * avrftdi.c: New file. + * avrftdi.h: (Ditto.) + * configure.ac: Add check for libftdi. + * config_gram.y: Add AVRFTDI and per-programmer USB string + keywords. + * lexer.l: (Ditto.) + * avrdude.conf.in: Add avrftdi and 2232HIO programmers. + * pgm.h: Add USB parameters. + * Makefile.am: Add avrftdi.c and avrftdi.h. + * AUTHORS: Mention the new authors. + * avrdude.1: Document the changes. + * doc/avrdude.texi: (Ditto.) + +2011-08-23 Joerg Wunsch + + bug #29585: Fix license + * doc/avrdude.texi: Add FDL as an option to the licensing + statement, as the savannah administration would like it + that way. + +2011-08-23 Joerg Wunsch + + Submitted by Darell Tan: + patch #7244: TPI bitbang implementation + * bitbang.c: Add TPI bitbang stuff. + * bitbang.h: (Ditto.) + * avr.c: (Ditto.) + * avr.h: (Ditto.) + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * serbb_posix.c: Wire bitbang_cmd_tpi into the struct pgm. + * serbb_win32.c: (Ditto.) + * par.c: (Ditto.) + * doc/avrdude.texi: Document the TPI bitbang support. + +2011-08-17 Joerg Wunsch + + Submitted by Grygoriy Fuchedzhy: + bug #31779: Add support for addressing usbtinyisp with -P option + * usbtiny.c (usbtiny_open): Add logic to distinguish multiple USBtinyISP + programmers by their bus:device tuple. + * doc/avrdude.texi: Document the new functionality. + * avrdude.1: (Ditto.) + +2011-08-16 Joerg Wunsch + + Submitted by Timon Van Overveldt: + bug #30268: Debugwire broken in avrdude-5.10 + * jtagmkII.c (jtagmkII_initialize): only try setting up a JTAG chain when + the programmer is using JTAG. + +2011-08-16 Joerg Wunsch + + bug #29636: AVRDude issues invalid CMD_CHECK_TARGET_CONNECTION + on the AVRISP-MKII + * stk500v2.c (stk500v2_program_enable): Rewrite the logic to + explain ISP activation failures. + * stk500v2_private.h: Fix the various STATUS_* constants; + AVR069 and AVR079 disagreed in their values, even though they + are apparently implementing the same logic behind. + +2011-08-16 Joerg Wunsch + + bug #29650: Programming timeouts in ATmega128RFA1 are too slow + * avrdude.conf.in (ATmega128RFA1): Bump write delay values for flash and + EEPROM to 50 ms. + +2011-08-16 Joerg Wunsch + + * avrdude.conf.in (ATmega8515, ATmega8535, ATmega48, ATmega88, ATmega88P, + ATtiny88, ATmega168, ATmega168P, ATmega328P): Bump delay value for STK500v2 + EEPROM write operation to 5, according to the respective XML files. + +2011-08-16 Joerg Wunsch + + Submitted by Darcy Houlahan: + bug #29694: error in avrdude.conf for attiny84 eeprom + * avrdude.conf.in (ATtiny84, ATtiny85): fix A7 bit in EEPROM write + command. + +2011-08-16 Joerg Wunsch + + Submitted by Durant Gilles: + * avrdude.conf.in (ATtiny4313): Fix flash addressing bits for manual ISP + algorithm. + +2011-08-16 Joerg Wunsch + + Submitted by Philip: + bug #31386: A "BUILD.svn" or similar "how to get started" doc would be helpful + * BUILD-FROM-SVN: New file. + +2011-08-15 Joerg Wunsch + + Submitted by Nic Jones: + bug #32539: [Documentation][Patch] Man page is misleading + re: Dragon & PDI + * doc/avrdude.texi: Update information about PDI connections + on AVR Dragon + +2011-08-12 Joerg Wunsch + + * usbasp.c: Add so this actually compiles + again. + +2011-08-12 Joerg Wunsch + + Contributed by tixiv@gmx.net: + bug #33345: File auto detection as binary doesn't open + file in binary mode on Windows + * fileio.c: Move the decision about opening files in + binary mode until before the fopen() call. + +2011-06-16 Thomas Fischl + + * avrdude.conf.in: Fix part id of ATtiny9. + +2011-05-28 Thomas Fischl + + Based on patch #7440 commited by Slawomir Fraƛ: + * usbasp.c: added TPI support for USBasp + * usbasp.h: (Ditto.) + +2011-05-11 Joerg Wunsch + + * avrdude.conf.in: Add support for ATmega168P. + +2011-05-11 Joerg Wunsch + + * avrdude.conf.in: Fix abbreviated name for ATmega324PA. + +2011-05-11 Joerg Wunsch + + Submitted by Lech Perczak: + bug #30946: Added support for ATmega8/16/32U2 + * avrdude.conf.in: Add ATmega8/16/32U2 entries. + +2011-05-11 Joerg Wunsch + + Submitted by David A Lyons: + patch #7393: Adding ATtiny4313 Device to avrdude.conf.in + * avrdude.conf.in: Add ATtiny4313 data. + +2011-05-11 Joerg Wunsch + + * usb_libusb.c: Bump timeout values to allow for slow clock + speeds. + * jtagmkII.c: (Ditto.) + +2011-03-04 Eric B. Weddington + + Thanks to Vitaly Chernookiy for the patch. + * avrdude.conf.in: Add support for atmega324pa. + * ChangeLog-2010: New file, rotate ChangeLog for new year. diff --git a/avrdude/ChangeLog-2001 b/avrdude/ChangeLog-2001 new file mode 100644 index 00000000..048dcf1c --- /dev/null +++ b/avrdude/ChangeLog-2001 @@ -0,0 +1,598 @@ +2001-12-30 Brian S. Dean + + * main.c: Update version. + + * avrdude.conf.sample: Clarify a comment. + + * avrdude.conf.sample: fix address bits + + * avrdude.1: Bring up to date. + +2001-12-29 Brian S. Dean + + * avrdude.conf.sample: Add the AVR3 progammer. + + * avr.c, avrdude.conf.sample, config_gram.y, main.c, pindefs.h: + Fix VCC assertion. + + Make the BUFF pin a mask like VCC to allow multiple pins to be + asserted at the same time (STK200 has two buffer enable lines). + + Add the STK200 programmer. + + Fix EEPROM address line selection for several parts. + +2001-12-15 Brian S. Dean + + * avrdude.conf.sample: fix spelling error + +2001-11-24 Brian S. Dean + + * Makefile: + Change "WARNING" to "NOTE" when overwriting the avrprog.conf file. + + * avrdude.1: Add my e-mail address. + + * avrdude.conf.sample: + Add comments about instruction formats. Correct an instruction + specification (cut&paste error). + +2001-11-21 Brian S. Dean + + * avr.c, config_gram.y, lexer.l, term.c: + In interactive mode, reset the address and length if we start dumping + a memory type different than the previous one. + + * avr.c, avrdude.conf.sample, config_gram.y: + Allow instruction data to be specified more flexibly, which can be + used to make the instruction input more readable in the config file. + + * main.c: Bump version number. + + * Makefile, avr.c, avr.h, avrdude.conf.sample, config.c, config.h: + * config_gram.y, fileio.c, fileio.h, lexer.l, main.c, term.c: + This is a major re-write of the programming algorithms. The Atmel + serial programming instructions are not very orthoganal, i.e., the + "read fuse bits" instruction on an ATMega103 is an entirely different + opcode and data format from the _same_ instruction for an ATMega163! + Thus, it becomes impossible to have a single instruction encoding + (varying the data) across the chip lines. + + This set of changes allows and requires instruction encodings to be + defined on a per-part basis within the configuration file. Hopefully + I've defined the encoding scheme in a general enough way so it is + useful in describing the instruction formats for yet-to-be invented + Atmel chips. I've tried hard to make it match very closely with the + specification in Atmel's data sheets for their parts. It's a little + more verbose than what I initially hoped for, but I've tried to keep + it as concise as I could, while still remaining reasonably flexible. + +2001-11-19 Brian S. Dean + + * avr.c, avr.h, avrdude.conf.sample, main.c, ppi.c, term.c: + Add support for ATMega163. + + Add support for reading/writing ATMega163 lock and fuse bits. + Unfortunately, in looking at the specs for other ATMega parts, they + use entirely different instruction formats for these commands. Thus, + these routines won't work for the ATMega103, for example. + + Add support for sending raw command bytes via the interactive terminal + interface. This allows one to execute any programming instruction on + the target device, whether or not avrprog supports it explicitly or + not. Thus, one can use this feature to program fuse / lock bits, or + access any other feature of a current or future device that avrprog + does not know how to do. + + Add in comments, an experimental instruction format in the + configuration file. If this works out, it would allow supporting new + parts and non-orthoganal instructions across existing parts without + making avrprog code changes. + +2001-11-17 Brian S. Dean + + * avrdude.conf.sample: Add ATMEGA163 part. + +2001-11-11 Brian S. Dean + + * main.c: output formatting + +2001-11-05 Brian S. Dean + + * ppi.c: Get ppi.h from /usr/include, not /sys. + +2001-10-31 Brian S. Dean + + * avr.c, avrdude.conf.sample, main.c: Correct version string. + Update read/write status more frequently. + Prefix ATMega parts with an 'm'. + +2001-10-16 Brian S. Dean + + * avr.c: Change ording for memory display. + + * config_gram.y: comment + + * avr.c, avr.h, avrdude.conf.sample, config_gram.y, lexer.l, term.c: + Fix (again, hopefully) page addressing for the ATMega parts. + + Rename the poorly chosen name "bank" to "page" for page addressing. + Atmel calls it "page" in their documentation. + + * config_gram.y, main.c: Fix an (non)exit. + Silence a couple of compiler warnings. + + * avr.c, avr.h, avrdude.conf.sample, config_gram.y, main.c: + Fix ATMega flash addressing. Add an ATMEGA16 part. Perform sanity + checking on the memory parameters for parts that do bank addressing. + +2001-10-15 Brian S. Dean + + * config.c, config.h, lists.h: Add copyright. + + * config_gram.y, lexer.l, lists.c: Add copyrights. + + * Makefile: Attempt to install avrprog.conf. + + * avrdude.conf.sample: Correct dt006 pinout. + + * Makefile, lexer.l: + Try and detect an old-style config file and print an appropriate error + message and a suggestion for correcting it. + + * Makefile, avr.c, avrdude.1, avrdude.conf.sample: Update the man page. + + Miscellaneous minor cleanups. + +2001-10-14 Brian S. Dean + + * Makefile, Makefile.inc, avr.c, avr.h, avrdude.conf.sample: + * config.c, config.h, config_gram.y, lexer.l, lists.c, lists.h: + * main.c, pindefs.h, term.c: + Use lex/yacc for parsing the config file. Re-work the config file + format using a more human-readable format. + + Read part descriptions from the config file now instead of hard-coding + them. + + Update usage(). + + Cleanup unused code. + + * Makefile, avr.c, avr.h, fileio.c, term.c: + First cut at supporting the ATmega 103 which uses bank addressing and + has a 128K flash. + + Due to the bank addressing required, interactive update of the flash + is not supported, though the eeprom can be updated interactively. + Both memories can be programmed via non-interactive mode. + + Intel Hex Record type '04' is now generated as required for outputing + memory contents that go beyond 64K. + +2001-10-13 Brian S. Dean + + * avr.c, avr.h, fileio.c, fileio.h, main.c, ppi.c, ppi.h, term.c: + * term.h: + Style fixes. + + * avr.c, avr.h, fileio.c, fileio.h, main.c, term.c: + Commit changes in preparation for support the ATMega line. + +2001-10-01 Brian S. Dean + + * Makefile: Don't override CFLAGS. + + * avrdude.1: Correct default pin assignment. + + * avr.c, fileio.c, main.c, ppi.c, term.c: + Remove debugging code - it served its purpose. + + Update copyrights. + +2001-09-21 Brian S. Dean + + * main.c: + Be sure to read the exit specs after the pin configuration has been + assigned, otherwise, we may apply the exit specs to the wrong pins. + + * main.c: debugging + +2001-09-20 Brian S. Dean + + * avrdude.1, avrdude.conf.sample, main.c: + Prefix pin config entries in the config file with a "c:". Later, I + might make part descriptions read in this way and we can use a + different letter for those (p). This will make the parsing easier to + distinguish between the entry types. + + * main.c: Initialize pin configuration description. + +2001-09-19 Brian S. Dean + + * AVRprog.pdf, Makefile, avr.c, avrdude.1, avrdude.conf.sample: + * avrdude.pdf, fileio.c, fileio.h, main.c, pindefs.h, term.c: + Make the pin definitions configurable based on entries in a config + file. This makes supporting other programmers much easier. + + Rename AVRprog.pdf to avrprog.pdf. + +2001-04-29 Brian S. Dean + + * avrprog-programmer.jpg: Remove this image file from the repository. + +2001-04-26 Brian S. Dean + + * avrprog-schematic.jpg: + Remove this image, use AVRprog.pdf as the preferred schematic for the + programmer. + +2001-04-25 Brian S. Dean + + * AVRprog.pdf, Makefile, avrdude.1: + Add a schematic provided by Joerg Wunch and also update the manual + page (also updated by Joerg) to reference the schematic. + +2001-02-25 Brian S. Dean + + * Makefile, Makefile.inc: Automate dependency generation. + +2001-02-08 Brian S. Dean + + * main.c: Turn off ready led when finished programming. + + * main.c: update version + + * avr.c, main.c: Correct a few comments. + + * Makefile, avr.c, term.c: Makefile : update dependencies + + avr.c : correct status led updates + + term.c : update status leds on write, make the address and length + arguments for dump optional. + +2001-01-26 Brian S. Dean + + * main.c: Version 1.1 + + * main.c: + Hmmm ... cvs co -D does not work. Change the revision + timestamp to a full date/time value. + + * avr.c, fileio.c, main.c, ppi.c, term.c: + Add a -V option to display the version information about each + component module. This is intended for support purposes, so that I + can tell unambiguously what version a binary out in the field is. + + Additionally, display a revision timestamp along with the version + number. This also is intended for aiding in support and is the Unix + time of the latest component module. Having this, should allow me to + do a "cvs co -D timestamp avrprog" and get exactly the source of the + version that is being reported. + + * fileio.c: + Return the maximum address (+1) written as opposed to the actual + number of bytes written. The presence of an Intel Hex address + record can cause these two number to be different; but the callers + of this routine need the former. + + * main.c: + Fix a place where we were exiting without applying the exit-specs. + + Wrap a long line. + + * avr.c, fileio.c: avr.c: Update a comment. + + fileio.c: Properly handle all the Intel Hex record types that I can + find information about. + +2001-01-25 Brian S. Dean + + * Usage, avr.h: Get rid of the Usage file. + +2001-01-24 Brian S. Dean + + * Makefile, avr.c, avr.h, main.c, pindefs.h, ppi.c: + Move pin definitions to their own file. + + First pass at providing feedback via the optionally connected leds. I + don't actually have any of these attached to my programmer, so I can + only guess as whether this is toggling them on and off correctly. + + Also, enable and disable the optional 74367 buffer. + + * avr.h, main.c, ppi.c, ppi.h, avr.c: + Rearrange the pinout for the programmer to be a little more logical. + Provide hooks to support a buffered programmer, pin 6 is now used to + enable a buffer that can be used to isolate the target system from the + parallel port pins. This is important when programming the target + in-system. + + Totally change the way the pin definitions are defined. Actually + set/clear pins based on the way more intuitive pin number, instead of + PPI data register, bit number combination. A table of pin data is + used so that any hardware inversion done by the parallel port is + accounted for, what you set is actually what appears at the pin. + Retain the old method for handling Vcc, however, because the hold + method is much easier to use when setting / retrieving multiple pins + simultaneously. + +2001-01-22 Brian S. Dean + + * Makefile: Don't gzip the man page. + + * avrdude.1: .Nm macro fix. Submitted by Joerg. + + * main.c: Cosmetic, don't output a preceding linefeed for usage(). + + * Makefile, avr.c, avr.h, fileio.c, term.c: + Makefile : use gzip -f for man page installation so that we don't get + prompted. + + avr.c avr.h fileio.c term.c : + + Change the avrpart data structure so that the typedef AVRMEM is + used as an index into an array for the sizes of the memory types + and also for pointers to buffers that represent the chip data for + that memory type. This removes a lot of conditional code of the + form: + + switch (memtype) { + case AVR_FLASH : + ... + } + + Also, re-code avr_read_byte() and avr_write_byte() to properly + handle the flash memory type without having to tell them whether + they should program the high byte or the low byte - figure that + out from the address itself. For flash memory type, these + routines now take the actual byte address instead of the word + address. This _greatly_ simplifies many otherwise simple + operations, such a reading or writing a range of memory, by not + having to worry about whether the address starts on an odd byte + or an even byte. + +2001-01-20 Brian S. Dean + + * avr.c, avr.h, fileio.c, fileio.h, main.c: + Return error codes instead of exiting, thus making sure that we exit + only via main() so that the exitspecs are properly applied. + + When reading input data from a file, remember how many bytes were read + and write and verify only that many bytes. + + Don't complain when an input file size is smaller than the memory size + we are programming. This is normal. + + * fileio.c: + Correct checksum calculation; failure to account for the value of the + record type was causing non-zero record types to be calculated + incorrectly. + + * Makefile, main.c: Makefile : install the man page + + main.c : drop the giant usage text now that we have a man page. + + * avrdude.1: + Add initial man page graciously contributed by Joerg Wunsch. Thanks + Joerg! + +2001-01-19 Brian S. Dean + + * term.c: + Accept abbreviations for eeprom and flash for the dump and write + commands. + + Fix small bug keeping 1 character command lines from being added to + the history. + + * term.c: + Implement enough state in cmd_dump so that if it is called with no + arguments, it successively dumps the next chunk of data of the same + previously specified length. + + * term.c, term.h, fileio.c, fileio.h, main.c, ppi.c, ppi.h: + * Makefile, avr.c, avr.h, avrprog.c: + The program was getting too large for a single file. Split it up into + more modular pieces. + + Also, accept command abbreviations as long as they are not ambiguous. + + * avrprog.c: + Add ability to specify the state of the power and reset pins on + program exit. Default to leaving the pins in the state they were when + we found them. + + Contributed by: Joerg Wunsch + +2001-01-18 Brian S. Dean + + * Makefile, avrprog.c: + Switch to using readline() for getting terminal input. I can't seem + to get the history capabilities working yet, but even so, it does + better handling of the prompt and strips newlines for us, so it's + still a win. + + Add a few new commands for terminal mode: help, sig, part, erase. + Display rudimentory help using the help command. + + Add some function prototypes. + + * Usage, avrprog.c: + Change -c (interactive command mode) to the more intuitive -t + (terminal mode). + + Make binary format the default for output. + + Update the parts table with corrections for old values and add some + new values. + +2001-01-15 Brian S. Dean + + * avrprog.c: + Automatically verify on-chip data with what we just programmed. + + * avrprog.c, Makefile: + Prepare the Makefile for integration into the FreeBSD ports tree. + + Fix a few "may be used uninitialized" bugs found by -Wall. + +2001-01-14 Brian S. Dean + + * avrprog.c: Free a buffer. + + * avrprog.c: + Use a smarter programming algorithm - read the existing data byte + first and only write the new one if it is different. + + Add -n option which is a test mode in which the chip is not actually + updated. This option does not affect writes in interactive mode. + + * avrprog.c: Add the "dump" and "write" interactive commands. + + * avrprog.c: + Correctly produce and handle "end of record" for intel hex files. + +2001-01-13 Brian S. Dean + + * avrprog.c: + Re-enable writing to the chip. I should probably should make this a + command-line selectable option so that I don't keep forgetting and + committing it with it disabled. + + * avrprog.c: + Add a newline before exiting due to command line errors. Perform a + bit more option compatibility testing between -c, -i, and -o. + + * avrprog.c: Add input file format auto-detection support. + + * Usage, avrprog.c: Say what the defaults are. + + * avrprog-programmer.jpg, Usage, avrprog-schematic.jpg: New files. + + * avrprog.c: Correct usage text. + + * avrprog.c: + Parameterize a few additional items per chip. Print out all per-chip + parameters on startup. Use the per-chip parameters in the code + instead of hard-coded values for the 2313. + + * avrprog.c: Fix filename assignment error. + + Clean up debugging code a little, utilize fileio() instead of making + direct calls to b2ihex(). + + * avrprog.c: A lot of general code cleanup. + + Re-work command line options to be more intuitive. + + Support Intel Hex input and output file formats. Provide hooks to + support Motorola S-Record as well. + + Add a few more part-specific parameters to the avrpart structure. + + Only write the flash or eeprom if the data to be written is not 0xff. + +2000-12-31 Brian S. Dean + + * avrprog.c: Update a comment. + + * avrprog.c: + Provide the ability to tie additionally tie pins 6-9 of the parallel + port to Vcc in order to supply more current. + + Fix a typo on the size of the S1200's Flash. + + Bring RESET low when programming is completed. + + * avrprog.c: + Correct pin connection comments. Elaborate a bit on Vcc connection. + + * avrprog.c: + Update after receiving some good feedback from Joerg Wunsch. We + should now be able to program AT90S1200's. + +2000-12-30 Brian S. Dean + + * avrprog.c: Don't limit eeprom addresses. + +2000-12-20 Brian S. Dean + + * Makefile, avrprog.c: + Add support for the 8515. Make the addition for other devices easier. + +2000-08-27 Brian S. Dean + + * avrprog.c: + Clear all bits except AVR_RESET when finished reading or programming + the Atmel device. + +2000-08-07 Brian S. Dean + + * avrprog.c: update announcement message + + * avrprog.c: Update announcement message. + + * avrprog.c: Return the correct return code from 'main()'. + + * avrprog.c: + Add ppi_pulse() function and fix ppi_toggle() to actully toggle + instead of pulse. + + Make all abnormal returns after the parallel port has been opened go + through a single exit point at the bottom of 'main()'. + +2000-08-06 Brian S. Dean + + * Makefile, avrprog.c: Makefile: add --pedantic compiler option + + avrprog.c: + + Add lots of comments, move getop() variable declarations to + the top of the program. + + Add a typedef name to the AVR memory type and use it for + function declarations. + + Add a usleep() delay in the sense loop to avoid becoming a cpu + hog. + + Print out a version string so that folks know what version of + the software they are running. + + Be sure and close the parallel device and the i/o file when + terminating abnormally. + + * avrprog.c: Print out version information when invoked. + + * Makefile, avrprog.c: Makefile: Add an install target. + + avrprog.c: + + Add license. + + Document the header a bit better. + + Add capability to read out and display the device signature bytes. + + Add capability to power the device from the parallel port. + + Eliminate debug print facility. + + Provide 'avr_cmd()' function. + + When memory locations don't program, generate a newline so that the + information is not overwritten and lost. + + Don't print out the message about needing to specify a file if the + user is not requesting an operation that requires the file. + +2000-08-05 Brian S. Dean + + * avrprog.c: Pring usage when no arguments are supplied. + + * Makefile, avrprog.c: Initial check-in + + * Makefile, avrprog.c: New file. + diff --git a/avrdude/ChangeLog-2002 b/avrdude/ChangeLog-2002 new file mode 100644 index 00000000..9bfa030a --- /dev/null +++ b/avrdude/ChangeLog-2002 @@ -0,0 +1,237 @@ +2002-12-12 Brian S. Dean + + * main.c: minor cleanup + +2002-12-07 Brian S. Dean + + * avrdude.1, main.c: + If the stk500 is being used, default to using the first serial port. + +2002-12-03 Brian S. Dean + + * avrdude.1: Mention STK500 support. + +2002-12-01 Brian S. Dean + + * stk500.c: Remove unused code. + + * CHANGELOG, stk500.c: + Document changes since the previous version in the CHANGELOG. + + Cleanup stk500.c a bit. + + * stk500.c: Fix cut and paste braino. + + * avr.c, avrdude.conf.sample, main.c, pgm.h, stk500.c: + The STK500 can perform paged read/write operations even on standard + "non-paged" parts. Take advantage of that and use the faster internal + routines of the STK500 for those parts as well. + + * avr.c, avr.h, avrpart.h, main.c, pgm.c, pgm.h, stk500.c: + Optimize reading and writing for the STK500 programmer if the part + supports paged reads and writes. This greatly decreases the + program/verify time from about 4.5 minutes down to about 10 seconds in + a 12K program size test case. + + Print out the hardware and firmware version for the STK500 if verbose + is enabled. + + * avrdude.conf.sample, avrpart.h, config_gram.y, lexer.l, pgm.h: + * ppi.c, ppi.h, stk500.c, stk500.h, stk500_private.h: + Add basic support for STK500. + +2002-11-30 Brian S. Dean + + * avrdude.conf.sample, config.c, config.h, config_gram.y, lexer.l: + * main.c, pgm.c, pgm.h, ppi.c, ppi.h, term.c, term.h, Makefile: + * avr.c, avr.h: + Seperate programmer operations out into a driver-like interface so + that programmers other than the direct parallel port connection can be + supported. + +2002-11-23 Brian S. Dean + + * CHANGELOG, main.c, term.c: + term.c - when in interactive terminal mode and dumping memory using + the 'dump ' command without any address information, + and the end of memory is reached, wrap back around to zero on + the next invocation. + + CHANGELOG - describe changes + + main.c - update version number + + * main.c: + When getting ready to initiate communications with the AVR device, + first pull /RESET low for a short period of time before enabling the + buffer chip. This sequence allows the AVR to be reset before the + buffer is enabled to avoid a short period of time where the AVR may be + driving the programming lines at the same time the programmer tries + to. Of course, if a buffer is being used, then the /RESET line from + the programmer needs to be directly connected to the AVR /RESET line + and not via the buffer chip. + +2002-11-06 Brian S. Dean + + * CHANGELOG: Update changelog. + + * avr.c, avr.h, main.c: Fix -Y option. Reported by Joerg Wunsch. + +2002-11-01 Brian S. Dean + + * CHANGELOG, main.c: Version update and CHANGELOG entry. + + * avr.c: + Be backward compatible with the 2-byte rewrite cycle counter which + appeared in version 2.1.0, but was changed to a 4 byte counter in + version 2.1.1. Reminded by Joerg Wunsch. + +2002-10-29 Brian S. Dean + + * CHANGELOG, avrdude.1, main.c: + Add '-V' (no verify) flag requested by Joerg Wunsch. Update the man + page. + +2002-10-13 Brian S. Dean + + * CHANGELOG, avrdude.1: Update man page and changelog. + + * main.c: Update version number. + +2002-10-12 Brian S. Dean + + * Makefile: Remove --pedantic and -g from the compiler options. + +2002-10-11 Brian S. Dean + + * avr.c, term.c: + Use a four byte value instead of a two byte value for the programming + cycle count stored at the end of EEPROM. It seems as though Atmel was + greatly conservative in claiming a 1000 count reliability for the + FLASH. I current have a part that has been reprogrammed 173330 times, + and counting. + + Fix a compiler warning. + + * avrdude.conf.sample: + Fix ATMega128 instruction encoding for reading the low and high fuse + bits. Thanks to Joerg Wunsch for tripping over this. + +2002-08-01 Brian S. Dean + + * avr.c, avrdude.1, main.c: + Move erase-rewrite cycle increment to within the chip erase routine so + that it is tracked no matter where the erase was initiated: command + line mode or interactive mode, without code duplicaiton. + + * CHANGELOG: Recent updates. + + * avr.c: Eliminate unused variables. + + * avr.c, avr.h, avrdude.1, fileio.c, main.c: + Implement a way of tracking how many erase-rewrite cycles a part has + undergone. This utilizes the last two bytes of EEPROM to maintain a + counter that is incremented each time the part is erased. + +2002-07-27 Brian S. Dean + + * avr.c, main.c: + Fix a typo in a comment. Display the size of memory being written. + Display the correct memory name in an error message (previously + hardcoded). + +2002-06-22 Brian S. Dean + + * CHANGELOG, avrdude.conf.sample: + Add support for ATtiny15 - contributed by Asher Hoskins + + +2002-04-23 Brian S. Dean + + * CHANGELOG: Say what changed. + +2002-04-07 Brian S. Dean + + * Makefile, avrdude.conf.sample: + Backup the config file to a timestamped name to keep from possibly + overwriting user-modified configs. + + Add read/write instructions for all memory types for ATMEGA103, + ATMEGA128, ATMEGA16, and ATMEGA8. + +2002-04-05 Brian S. Dean + + * avrdude.conf.sample: + Add support for ATMEGA128; untested; requested by Jeff Gardner + . + +2002-02-15 Brian S. Dean + + * avrdude.conf.sample: Minor ordering. + + * CHANGELOG, main.c: Update version numbers. + +2002-02-14 Brian S. Dean + + * CHANGELOG: Summarize latest updates. + + * avrdude.conf.sample, config_gram.y: + Make pwroff_after_write a yes/no field instead of a numeric. + + * avrdude.conf.sample: Document the pwroff_after_write flag. + + * avr.c: Enable the extra part verbosity when verbosity >= 3. + + * avr.c, avr.h, avrdude.conf.sample, config_gram.y, lexer.l: + * main.c, term.c: + Fix error reporting by avr_write_byte(). + + Fix setting of status LEDs under various write-fail conditions. + + Add a flag to indicate that a memory type requires the device to + possibly be powered off and back on after a write to it. This is due + to a hardware problem on some Atmel devices, see: + + http://www.atmel.com/atmel/acrobat/doc1280.pdf + + Add greater verbosity to the part-display code when verbose>1 to + display avrprog's encoding of the defined programming instructions. + This is primarily for debugging purposes. + + + Part updates: + + * add the AT90S4414 part + + * add fuse and lock bit access instructions for the AT90S1200, + AT90S4434, and AT90S8515. + + * add the pwroff_after_write flag to the fuse bits for the AT90S2333 + and AT90S4433 parts + +2002-02-09 Brian S. Dean + + * avrdude.conf.sample: + Updates to the 2333 and 4433 parts, contributed by Joerg Wunsh. + +2002-01-18 Brian S. Dean + + * CHANGELOG: Add changelog. + +2002-01-12 Brian S. Dean + + * main.c: Add (c) to copyright. + + * fileio.c, fileio.h, lexer.l, lists.c, lists.h, main.c: + * pindefs.h, ppi.c, ppi.h, term.c, term.h, avr.c, avr.h: + * config.c, config.h, config_gram.y: + Update version number. Update copyright. + + * avrdude.1: Update copyright and add description of "default". + + Submitted by: Joerg Wunsch + + * avr.c, term.c: + Fix programming of write-only memories (such as lock bits on the + 2313). + diff --git a/avrdude/ChangeLog-2003 b/avrdude/ChangeLog-2003 new file mode 100644 index 00000000..1115bdfb --- /dev/null +++ b/avrdude/ChangeLog-2003 @@ -0,0 +1,1095 @@ +2003-12-01 Eric B. Weddington + + * doc/avrdude.texi: Update devices and programmers supported. + +2003-12-01 Eric B. Weddington + + * doc/avrdude.texi: Add missing -D option to user manual. + [This fixes bug #6804] + +2003-11-30 Jan-Hinnerk Reichert + + * avrpart.c,main.c: Moved list_parts() and locate_part() + from main.c to avrpart.c. + * avrpart.h: Added prototypes for list_parts() and + locate_part(). + +2003-11-30 Jan-Hinnerk Reichert + + * avrpart.c, avr.c: Moved elementary functions on types + OPCODE, AVRMEM and AVRPART from avr.c to new file avrpart.c. + * avr.h: Removed prototypes for moved functions. + * avrpart.h: Added prototypes for functions in avrpart.c. + * Makefile.am: Added new file avrpart.c. + +2003-11-28 Michael Mayer + + * lexer.l: New programmer type "butterfly". + * config_gram.y: New token K_BUTTERFLY. + * avrdude.conf.in: Added programmer definition. + * butterfly.c, butterfly.h: Cloned from avr910.?, changed to work + with the Atmel Butterfly device. + * Makefile.am: Added butterfly.[ch] to avrdude_SOURCES. + +2003-11-26 Joerg Wunsch + + * main.c: Make the -U parser tolerate colons in filenames. + * avrdude.1, doc/avrdude.texi: Document the -U changes. + +2003-11-21 Jan-Hinnerk Reichert + + * ppi.c: Major speed tuning. Since ioctl() is expensive read from + shadowregisters where possible. + +2003-11-19 Eric B. Weddington + + * NEWS: Update news from items in ChangeLog. + +2003-11-19 Theodore A. Roth +[Contributed by Jan-Hinnerk Reichert ] + + * avr.c (avr_write_byte_default): Improve polling algorithm to speed up + programming of byte oriented parallel programmers. + +2003-11-14 Brian S. Dean +[Contributed by Erik Christiansen ] + + * avrdude.conf.in: + Add ATmega64 part. + +2003-11-08 Joerg Wunsch + + * avrdude.conf.in: + Add "fuse" and "lock" definitions for the AT90S8535. Actually, + this is stolen from the AT90S8515 since the datasheet says it's + the same there. + +2003-10-13 Bill Somerville + + * stk500.c (stk500_paged_write): Limit blocks written to no bigger + than memory device size. + (stk500_paged_write): Send whole block at once. + (stk500_paged_load): Limit blocks read to no bigger than memory + device size. + [This fixes bug #5713.] + +2003-10-13 Eric B. Weddington + + * avrdude.conf.in: Fix for unterminated character error. + +2003-10-13 Eric B. Weddington + + * avrdude.conf.in: Add ATmega8515 definition. + Contributed by: Matthias Weißer + * NEWS: Add note about ATmega8515 definition. + +2003-09-24 Eric B. Weddington + + * doc/TODO: Updated TODO list. + +2003-09-22 Eric B. Weddington + + * windows/Makefile.am: Correct makefile so loaddrv does not link + to Cygwin DLL. + +2003-09-18 Eric B. Weddington + + * doc/avrdude.texi: Minor corrections. Change description of -P + to reference platform dependencies. + +2003-09-16 Eric B. Weddington + + * stk500.c: If writing flash, skip empty pages in paged write. + +2003-09-06 Theodore A. Roth + + * NEWS: Add 'Current:' header. + * configure.ac (AC_INIT): Add cvs back to version since we're + back in dev cycle (post release). + +2003-09-06 Theodore A. Roth + + * AVRDUDE 4.2.0 has been released (cvs release tag is "release_4_2_0"). + +2003-09-06 Theodore A. Roth + + * NEWS: Update for 4.2.0 release. Add note about read/write of fuses + support for avr910. + * configure.ac (AC_INIT): Set version to 4.2.0. + +2003-09-05 Theodore A. Roth +[Contributed by Jan-Hinnerk Reichert ] + + * avr.c (avr_read_byte): If pgm->read_byte method fails, retry with + avr_read_byte_default. + * avr.c (avr_write_byte): If pgm->write_byte method fails, retry with + avr_write_byte_default. + * avr910.c (avr910_cmd): Implement using universal command. + +2003-09-04 Theodore A. Roth + + * Makefile.am: Change AM_CPPFLAGS to avrdude_CPPFLAGS. + Define avrdude_CFLAGS. + * configure.ac: Set ENABLE_WARNINGS to "-Wall" if using gcc. + +2003-09-02 Eric B. Weddington + + * doc/avrdude.texi: Add note about privileges needed to load + the giveio driver for Windows. + +2003-08-29 Brian S. Dean + + * avrdude.1: + * main.c: + Perform an auto erase before programming if the flash memory is + anywhere specified to be written by any of the -U requests. + + To remain backward compatible with previous versions, disable this + feature if any of the old-style memory specification operations are + specified (-i, -o). + + Implement the -D option to explicitly disable the auto erase default. + + Deprecate the old-style memory specification options (-f, -i, -I, -m, + and -o) in favor of the new -U option which allows one to operate on + multiple memories on a single command line. + +2003-08-28 Eric B. Weddington + + * avr910.c: + * fileio.c: + * main.c: + * stk500.c: + More code cleanup to remove warnings. + +2003-08-27 Theodore A. Roth + + * main.c (update_progress_no_tty): Properly terminate progress. Also + fixes stk500 problem where number of bytes written is less than a page. + +2003-08-27 Theodore A. Roth + + * avrdude.spec.in: Fix broken rpmbuild on RedHat-9. + +2003-08-25 Eric B. Weddington + + * fileio.c: + * main.c: + * ppiwin.c: + * ser_posix.c: + * stk500.c: + Minor code cleanup to remove warnings. + +2003-08-21 Brian S. Dean + + * avrdude.1: + * main.c: + + Introduce a new option, -U, for performing memory operions. + Its argument is a 4 field string (fields seperated by colons) + which indicate what memory type to operate on, what operation + to perform is (read, write, or verify), the filename to read + from, write to, or verify against, and an optional file format + field. Multple -U options can be specified to operate on more + than one memory at a time with a single invocation. For + example, to update both the flash and the eeprom at the same + time one can now specify the following: + + avrdude -p -e -U flash:w:main.hex:i -U eeprom:w:eeprom.hex:i + +2003-08-20 Brian S. Dean + + * ppiwin.c: + Timing related fixes for the Windows platform. Several folks have + reported that this patch fixes verify errors on the Windows platform + that are apparently timing related. Submitted by: Alex Shepherd + , who indicates that this patch was based on + code from the UISP project. + +2003-08-01 Theodore A. Roth + + * avrdude.1: Document the -q option. + * doc/avrdude.texi: Document the -q option. + Fix some typos left over from pasting in man output. + +2003-07-30 Brian S. Dean + + * main.c: Add elapsed time information to the new progress bar. + +2003-07-29 Theodore A. Roth + + * avr.c: + * avr.h: + * avr910.c: + * main.c: + * stk500.c: + New progress reporting implementation. + +2003-07-24 Joerg Wunsch + + * avrdude.1: + * doc/avrdude.texi: + * pgm.c: + * pgm.h: + * stk500.c: + * stk500_private.h: + * term.c: Add support for displaying and setting the various + operational parameters of the STK500 (Vtarget, Varef, clock). + +2003/07/22 Brian S. Dean + + * avrdude.conf.in: + Add 'picoweb' programming cable programmer. + Contributed by Rune Christensen . + +2003-06-18 Brian S. Dean + + * avrdude.conf.in: + Add the 'sp12' (Steve Bolt's) programmer. + Submitted by Larry Barello . + +2003-06-17 Brian S. Dean + + * avrdude.conf.in: + Properly identify the "ALF" programmer. + + Extend ATmega8 calibration memory to support all 4 calibration bytes. + Savannah bug #3835. Submitted by Francisco T. A. Silva + . + + Add a few AVR910 programmer device codes. Savannah bug #3569 - sorry + I can't tell who submitted this to give proper credit. + + Add support for the ATtiny12. Submitted by Pontifex + +2003-05-22 Brian S. Dean + + * avr.c: + * avr.h: + * fileio.c: + Optimize flash memory handling a little bit by ignoring 0xff data that + resides above the last non-0xff data value in the address space. Only + do this for flash memory since writing a 0xff to flash is a no-op. + This has the affect of creating smaller output files when dumping + memory contents from flash if the program in flash does not consume + the whole memory space. It also results in shorter programming times + when avrdude is asked to load a file into flash that has lots of 0xff + filled data past the last non-0xff data value. + +2003-05-13 Theodore A. Roth + + * avr910.c (avr910_paged_write_flash): Add code to send the 'm' + command ("issue page write" cmd) for each page. + +2003-05-13 Theodore A. Roth + + * avrdude.conf.in: Add pagel and bs2 entries for at90s1200 device. + +2003-05-13 Theodore A. Roth + + * doc/TODO: Add note about avr910 device codes. + +2003-05-04 Theodore A. Roth + + * configure.ac: Check for ncurses library (since it can be a + replacement for termcap). + +2003-05-02 Theodore A. Roth + + * avrdude.conf.in: Add avr decodes for devices known in avr910 + firmware version 2.3. + Add missing stk500 devocde for 2343. + +2003-04-23 Eric B. Weddington + + * fileio.c: Fix for bug #3293. Set correct open mode for raw format + for Windows. + +2003-04-19 Brian S. Dean + + * avrdude.1: + * fileio.c: + * fileio.h: + * main.c: + Implement and "immediate mode" for file input - this allows + one to specify byte values on the command line instead of via + a file. This can be good for specifying fuse bytes and + eliminates the need to create single-byte files or using + interactive terminal mode for these single-byte memories. + Requested by several folks on the mailing list. + +2003-04-18 Theodore A. Roth + + * configure.ac: Add cvs suffix back to version. + * doc/TODO: Add a few items. + +2003-04-18 Theodore A. Roth + + * AVRDUDE 4.1.0 has been released (cvs release tag is "release_4_1_0"). + +2003-04-17 Theodore A. Roth + + * configure.ac: Set version to 4.1.0. + * doc/avrdude.texi: Add note about avr910 programmer type. + +2003-04-17 Eric B. Weddington + + * NEWS: Replace TBD with new release version. + +2003-04-17 Eric B. Weddington + + * avrdude.conf.in: Change name of pony programmer to pony-stk200 + to better describe the hardware (PonyProg is software that works + with various hardware). + +2003-04-16 Eric B. Weddington + + * avrdude.conf.in: Add support for ATtiny26 + Submitted by Artur Lipowski + * NEWS: List new devices supported: ATtiny26 + +2003-04-16 Eric B. Weddington + + * avrdude.conf.in: Add support for ATmega8535 + Submitted by Alexander Peter + * NEWS: List new devices supported: ATmega8535 + +2003-04-09 Theodore A. Roth + + * avr910.c: Reading a 16 bit word in paged load needs to swap the + bytes since the 'R' command returns MSB first and the internal buffer + stores LSB first. + +2003-04-07 Theodore A. Roth + + * stk500.c: Don't print out read/write byte progress unless the verbose + option is given. + +2003-04-05 Theodore A. Roth + + * avr910.c: Re-add the avr910 byte read/write methods which were + removed in my previous patch. Terminal mode read/writes are broken + without those methods. D'oh! + +2003-04-05 Theodore A. Roth + + * avr910.c: Refactor to allow probing for auto addr increment. If auto + incr supported by programmer hw, don't send addr for every byte. + +2003-04-03 Eric B. Weddington + + * confwin.c: Fix bug that allows garbage for non-existent user + config filename on Windows. + +2003-03-29 Brian S. Dean + + * avrdude.conf.in: + Add the ATmega32 part. This part definition was contributed by: + Daniel Williamson and + Ruwan Jayanetti + The resulting part definition used was actually somewhat of a merge of + the two submitted definitions. + +2003-03-24 Theodore A. Roth + + * NEWS: Add note about avr910 support. + +2003-03-23 Theodore A. Roth + + * avr.c (avr_write): Add call to pgm->write_setup() before the write + loop. + * avr910.c: Change all show_func_info() calls to no_show_func_info(). + Add read/write to/from flash/eeprom memory functionality. + * pgm.c: Initialize pgm->write_setup. + * pgm.h: Add write_setup field to PROGRAMMER structure. + * ser_posix.c: Remove unneeded cast in verbosity code. + +2003-03-23 Theodore A. Roth + + * ser_posix.c: Limit verbose output to 2 chars. + +2003-03-23 Theodore A. Roth + + * ser_posix.c: Add verbose level > 3 output for send and recv functions. + +2003-03-23 Theodore A. Roth + + * avr.c: Add avr_read_byte_default(). + Have avr_read_byte() call pgm->read_byte() or avr_read_byte_default(). + Add avr_write_byte_default(). + Have avr_write_byte() call pgm->write_byte or avr_write_byte_default(). + * pgm.c: Initialize pgm->write_byte and pgm->read_byte. + * pgm.h: Add write_byte and read_byte fields to struct programmer_t. + +2003-03-17 Theodore A. Roth + + * avrdude.conf.in: Fix typo for devicecode deprecation comment. + +2003-03-17 Eric B. Weddington + + * avrdude.conf.in: Add Bascom SAMPLE programmer. + Submitted by Larry Barello + +2003-03-16 Theodore A. Roth + + * avr.c (avr_read): Use pgm->read_sig_bytes to read signature bytes if + available. + * avr910.c (avr910_vfy_cmd_sent): New function. + (avr910_chip_erase): Add support for chip erase. + (avr910_enter_prog_mode): New function. + (avr910_leave_prog_mode): New function. + (avr910_initialize): Add code to select device type and enter prog mode. + (avr910_close): Leave programming mode before closing serial port. + (avr910_read_sig_bytes): New function. + (avr910_initpgm): Add avr910_read_sig_bytes method to pgm initializer. + * avrdude.conf.in: Add note about deprecating devicecode. + Change all occurences of devicecode to stk500_devcode. + Add avr910_devcode to a few parts for testing. + * avrpart.h (struct avrpart): Change devicecode field to stk500_devcode. + (struct avrpart): Add avr910_devcode field. + * config_gram.y: Add K_STK500_DEVCODE and K_AVR910_DEVCODE tokens. + Generate an error if devicecode is found in the config file. + Handle parsing of avr910_devcode and stk500_devcode. + * lexer.l: Handle parsing of avr910_devcode and stk500_devcode. + * pgm.c: Initialize pgm->read_sig_bytes field. + * pgm.h: Add pgm->read_sig_bytes field. + * stk500.c: Use stk500_devcode instead of devicecode. + +2003-03-16 Theodore A. Roth + + * avrdude.conf.in: Add avr910 and pavr programmers. + * config_gram.y: Add parsing of avr910 programmer. + * lexer.l: Add avr910 token. + * avr910.c: [this is still work in progress] + Add some debug output. + Add probe for programmer presense. + * main.c: Set port to default_serial if programmer type is avr910. + +2003-03-13 Theodore A. Roth + + * ser_posix.c, ser_win32.c, serial.h: + Change baud from int to long to avoid a 16-bit int overflow. + +2003-03-12 Theodore A. Roth + + * Makefile.am (avrdude_SOURCES): Add avr910.[ch], serial.h and + ser_posix.c files. + * avr910.c: New file (stubs for avr910 serial programmer). + * avr910.h: New file. + * ser_posix.c: New file. + * ser_win32.c: New file (just stubs for now). + * serial.h: New file. + * stk500.c: Move all the code for accessing the posix serial ports + into ser_posix. This will make a native win32 port easier and allows + the avr910 programmer to share the serial code. + +2003-03-12 Theodore A. Roth + + * configure.ac (AC_INIT): Set version to 4.0.0cvs since we're done + with 4.0.0 release. + +2003-03-12 + + * AVRDUDE 4.0.0 has been released (cvs release tag is "release_4_0_0"). + +2003-03-11 Theodore A. Roth + + * Makefile.am: Add CLEANFILES to remove all files from a make. + * doc/Makefile.am: Ditto + +2003-03-11 Theodore A. Roth + + * windows/Makefile.am: Fix uninstall-local rule (forget the $$file + part of the rm command). + +2003-03-11 Theodore A. Roth + + * AUTHORS: Updated. + * CHANGELOG: Move contents to NEWS and remove file. + * ChangeLog: All of the changes for this year. + * ChangeLog-2001: All 2001 changes. + * ChangeLog-2002: All 2002 changes. + * Makefile.am (EXTRA_DIST): Remove CHANGELOG and and Change-200[12]. + * NEWS: Moved contents of CHANGELOG file here. + * README: Add note pointing to savannah site. + +2003-03-11 Eric Weddington + + * doc/avrdude.texi: + Add Install and Documentation sections for Windows. Fix typo. + +2003-03-10 Theodore A. Roth + + * Makefile.am: * Makefile.am (EXTRA_DIST): Add CHANGELOG. + +2003-03-10 Brian S. Dean + + * stk500.c: Disable debugging printf. + + * configure.ac: Update version number in preparation for release. + +2003-03-10 Theodore A. Roth + + * doc/avrdude.texi: + Add comment before each node to make them stand out better. + Use @option{} command for options instead of @code{}. + Merge FreeBSD and Linux platform dependent information. + +2003-03-10 Brian S. Dean + + * avrdude.1: Minor man page updates to better reflect reality. + +2003-03-10 Joerg Wunsch + + * bootstrap: + Export all the AUTO* variables. Hopefully, that way the generated + Makefile might get them correctly. + + * bootstrap: + Export ${AUTOCONF} so automake will find it by whatever name it will be + called today. + +2003-03-06 Eric Weddington + + * doc/avrdude.texi: + Add notes about ability to list parts and list programmers in the + config file in -p and -c descriptions. Change info about where to + find Windows search method in -C description. + + * main.c: + Change software version from hardcoded value to getting it from + the configuration. + +2003-03-06 Theodore A. Roth + + * avrdude.spec.in: * avrdude.spec.in: Add docs sub-package. + Add %post and %preun scriptlets for handling info files. + + * configure.ac, doc/Makefile.am: + * configure.ac: Add --enable-versioned-doc option and set DOC_INST_DIR. + * doc/Makefile.am: Add rules to install docs in DOC_INST_DIR. + + * doc/Makefile.am: + Delete the lines which where commented out in previous commit. + + * configure.ac, doc/Makefile.am: + * configure.ac: Remove hack to make work with automake-1.5. + * doc/Makefile.am: Remove extra rules that were needed to work with + automake-1.5. + + * bootstrap: + * bootstrap: Force use of autoconf-2.57 and automake-1.7.x. + +2003-03-05 Joerg Wunsch + + * avrdude.conf.in: Add a definition for the popular Ponyprog dongle. + + Submitted by: Daniel Williamson + +2003-03-05 Brian S. Dean + + * main.c: + Check the programmer type against 'STK500' instead of the programmer + name when checking to see if we should default to the default_serial + port instead of the default_parallel port. This has us do the right + thing for the new 'avrisp' programmer. + + * stk500.c: + Make the page size used for non-paged parts for the 'paged_write' + command be 128 bytes. This cuts 6 seconds off the programming time + for uploading a 6K file into an AT90S8515 vs the time loading the same + file using a 16 byte buffer, and the response feedback is still good. + + * avr.c, stk500.c: + Fix stk500 page write (Program Page command). This is supported after + all on non-paged-memory parts. The problem was that the page size was + defaulting to 256 (maximum for the stk500), but the timeout for a + response from the stk500 before declaring it dead was only 0.5 + seconds. But it takes much longer than 0.5 seconds to program 256 + bytes, so we just weren't waiting long enough. + + Fix this in two ways - increase the timeout to 5 seconds, and decrease + the page size to 16 bytes for non-paged parts. The programming time + for 16 bytes is short enough to provide the user with some feedback + that something is happening. + + * avr.c, stk500.c: + Don't call the programmer's 'paged_write' routine unless the memory + itself is paged as it doesn't appear to work otherwise. + + * avrdude.conf.in: Fix device codes for at90s8515 and at90s8535. + + * avrdude.conf.in: + Add PAGEL and BS2 parms for parts I have datasheets for. + + * config_gram.y: + Do that last commit slightly differently - this way results in no + shift-reduce conflicts. + + * config_gram.y: + It shouldn't be an error to have an empty configuration file. This + causes some shift-reduce conflicts, but I think they are OK. + + * main.c: + Print out a list of valid parts for '-p ?' and a list of valid + programmers for '-c ?'. + +2003-03-04 Eric Weddington + + * doc/avrdude.texi: Minor Windows doc corrections. + + * doc/TODO: Add TODO file. + + * avrdude.conf.in: Add AVR ISP programmer. + +2003-03-04 Brian S. Dean + + * stk500.c: + Don't try to set extended device programming parameters if they + haven't been specified in the config file for the part. + + * stk500.c: Set extended device parameters for all firmware versions. + + * stk500.c: + First attempt at supporting STK500 firmware past 1.10. Thanks to + Jason Kyle for the needed protocol information. + +2003-03-03 Theodore A. Roth + + * doc/Makefile.am: + * doc/Makefile.am: Add ps and pdf rules since they aren't supplied by + automake versions prior to 1.7. + + * doc/avrdude.texi: + * doc/avrdude.texi: Add node and menu information for the info system. + + * Makefile.am, configure.ac, doc/Makefile.am, doc/avrdude.texi: + * Makefile.am (SUBDIRS): Add doc dir. + * configure.ac (AC_CONFIG_FILES): Add doc/Makefile. + * doc/Makefile.am: New file. + * doc/avrdude.texi: Use automatically generated version.texi. + +2003-03-02 Brian S. Dean + + * doc/avrdude.texi: Initial manual. + +2003-02-27 Theodore A. Roth + + * term.c: * term.c: Use fgets() if readline() is not available. + +2003-02-27 Joerg Wunsch + + * bootstrap: + Oops, accidentally spammed the repository with my private version of + "bootstrap". Back out that change. + + * bootstrap, lexer.l: + Ignore \r as white space, to make the Windows people happy. + +2003-02-27 Theodore A. Roth + + * Makefile.am (EXTRA_DIST): Add avrdude.spec and make entries one + per line so future patches are obvious as to what changed. + * avrdude.spec.in: New file to support creation of binaries in rpm + format. + * configure.ac (AC_OUTPUT): Add avrdude.spec. Reorder so that + Makefile is the last entry. + +2003-02-26 Theodore A. Roth + + * Makefile.am (SUBDIRS): Add windows dir. + * configure.ac: If $target is a windows system, build whats in + windows sub dir. + * windows/Makefile.am: New file. + +2003-02-25 Theodore A. Roth + + * ChangeLog: Point reader to the CHANGELOG file. + * Makefile.am (EXTRA_DIST): Rename avrdude.conf.sample to + avrdude.conf.in. + Remove avrdude.conf and distclean-local rules. + Add install-exec-local and backup-avrdude-conf rules. + * avrdude.conf.in: + Set default_parallel to "@DEFAULT_PAR_PORT@" for autoconf expansion. + Set default_serial to "@DEFAULT_SER_PORT@" for autoconf expansion. + * configure.ac: Add call to AC_CANONICAL_{BUILD,HOST,TARGET} macros. + Set DEFAULT_PAR_PORT and DEFAULT_SER_PORT based on $host. + Add copyright header. + Define avrdude_version so AC_INIT and AM_INIT_AUTOMAKE are sure + to get the same version. + + * avrdude.conf.in, avrdude.conf.sample: + Renamed avrdude.conf.sample to avrdude.conf.in. + +2003-02-25 Eric Weddington + + * ppiwin.c: CRs again. + + * confwin.c, confwin.h: Get rid of CRs. + + * main.c, Makefile.am: Get rid of CRs again. + +2003-02-24 Joerg Wunsch + + * avrdude.1: Atmel has rearranged their web site, so now the AVR + docs have been moved to a more logically sounding URL. + +2003-02-24 Eric Weddington + + * Makefile.am, main.c: Integrate Windows search of config files. + + * confwin.c, confwin.h: config file search on Windows. + + * ppiwin.c: Change port value from lpt1alt to lpt3. Other + formatting changes. + + * windows/giveio.c: + Add giveio device driver source. Requires MS DDK to build. + + * windows/giveio.sys: Add giveio device driver binary. + + * giveio.sys, install_giveio.bat, remove_giveio.bat, status_giveio.bat: + Move Windows specific files. + + * windows/loaddrv.c, windows/loaddrv.h, windows/remove_giveio.bat: + * windows/status_giveio.bat, windows/install_giveio.bat: + Add Windows specific files. + + * main.c: Usage back to stderr. + +2003-02-22 Brian S. Dean + + * CHANGELOG: Add note about .avrduderc. + + * avr.c, avrdude.conf.sample, avrpart.h, config_gram.y, main.c, + * par.c, pgm.c, pgm.h: + Add the ability to read a per-user config file located at + $HOME/.avrduderc. Entries from .avrduderc take precedence over those + from the system wide config file in ${PREFIX}/etc/avrdude.conf. + + Track and display the config file name and line number when we print + out the available parts and programmers. This is useful in case + someone has overridden a definition in their .avrduderc file and is + wondering why the definition in the system wide config file is not + being used. + + Remove the default programmer 'stk500' from the distributed config + file. + + * CHANGELOG: Spelling. + +2003-02-21 Brian S. Dean + + * CHANGELOG: + Put some stuff in the CHANGELOG for this upcoming new version before I + forget. + + * main.c: + Update comment due to removal of the default parallel port pin config. + + * config.c, config.h, config_gram.y, lexer.l, main.c: + * avrdude.conf.sample: + Introduce 'default_programmer' to the config file instead of requiring + one of the programmers to be tagged "default" within its definition. + + Also, axe the notion of a compiled-in default programmer. It is + kind've pointless now that nearly all configuration comes from the + config file, thus, avrdude is not very useful without the config file, + and thus, having a programmer compiled-in offers little or no benefit. + +2003-02-21 Eric Weddington + + * main.c: Change usage text to be verbose. + + * giveio.sys: Add Windows parallel port device driver (binary). + + * install_giveio.bat, remove_giveio.bat, status_giveio.bat: + Windows batch files to work with giveio.sys. + +2003-02-21 Brian S. Dean + + * avrdude.conf.sample, config.c, config.h, config_gram.y, lexer.l: + * main.c: + Add port name defaults to the config file instead of hard-coding. + This adds 'default_parallel' and 'default_serial' keywords to the + grammar, which take quoted string arguments. + + * avrdude.conf.sample: + Document the recent additions to the config file. + + * stk500.c, avr.c, avrpart.h, config_gram.y, lexer.l, par.c: + Add the ability to specify which pin to pulse when retrying entry into + programming mode. Use 'retry_pulse' in the per-part specification + that can currently take values of 'reset' or 'sck', the default being + 'sck' which preserves the previous behaviour. Some newer parts + indicate that /RESET should be pulsed, while older parts say to pulse + SCK. + +2003-02-20 Eric Weddington + + * main.c, par.c: + Make verbose global. Make debug code in par_cmd() based on verbose=2. + +2003-02-20 Brian S. Dean + + * stk500.c: Fix pseudo/full parallel mode selection logic. + + * avrdude.conf.sample: + Woops, didn't really mean to commit those changes that slipped in with + the last commit. Those were just there for testing. + + * avr.c, avrdude.conf.sample, avrpart.h, config_gram.y, lexer.l: + * stk500.c: + Add 'serial' and 'parallel' keywords to the grammar so that one can + say whether parts support these programming modes or not. Possible + values for 'serial' are 'yes' or 'no'. Possible values for 'parallel' + are 'yes', 'no', or 'pseudo'. Add a bit mask of flags to the AVRPART + structure to capture these settings. Use these within + stk500_initialize() to set the device parameters correctly. + + Defaults for 'serial' and 'parallel' are 'yes' unless specified + otherwise. + +2003-02-20 Eric Weddington + + * Makefile.am, ppiwin.c: Get rid of CRs. + + * Makefile.am: Add ppiwin.c to avrdude_SOURCES. + + * ppiwin.c: Added ppiwin.c: Windows parallel port driver. + + * stk500.c: + Add error message for fail to enter programming mode. Fix typos. + +2003-02-20 Brian S. Dean + + * avr.c, avrdude.conf.sample, avrpart.h, config_gram.y, lexer.l: + Add a few parameters needed for parallel programming: assignment of + PAGEL and BS2 signals and the disposition of the reset pin + ('dedicated' or 'io'). + +2003-02-20 Theodore A. Roth + + * avrdude.1: Fix spacing for m169 entry. (tabs not spaces ;-) + +2003-02-20 Brian S. Dean + + * avrdude.1, fileio.c, main.c: Add Motorola S-record support. + + Submitted by: "Alexey V.Levdikov" + +2003-02-19 Theodore A. Roth + + * avrdude.1: Add m169 to list of supported targets. + +2003-02-19 Joerg Wunsch + + * avrdude.conf.sample, avrdude.1: + My colleague contributed a part definition for the AT90S2343. + + Submitted by: Mirko Kaffka + +2003-02-18 Theodore A. Roth + + * avrdude.conf.sample: + Add support for mega169. (tested with stk500 with 1.7 firmware) + + * avrdude.conf.sample: + Add commments to separate parts (makes it easier for the eye to parse). + +2003-02-15 Theodore A. Roth + + * Makefile.am: Add $srcdir to sample config filename so that + building in a separate dir works. + +2003-02-15 Joerg Wunsch + + * Makefile.am: + Only GNU make sets $< in non-inference rules, so rather explicitly + spell the source file(s) to remain compatible. + +2003-02-14 Theodore A. Roth + + * Makefile.am: Add distclean rule and EXTRA_DIST list to get 'make + distcheck' to succeed. + + These changes add basic support for a autoconf/automake based + build system. + + * .cvsignore: Ignore autoconf files. + * AUTHORS: New file. + * ChangeLog: New file. + * Makefile: Removed file. + * Makefile.am: New file. + * NEWS: New file. + * README: New file. + * bootstrap: New file. + * configure.ac: New file. + * avr.c: Include ac_cfg.h (generated by autoconf). + * config.c: Include ac_cfg.h. + Include config_gram.h instead of y.tab.h. + * config.h: If HAS_YYSTYPE is not defined, define YYSTYPE. + * config_gram.y: Include ac_cfg.h. + * fileio.c: Include ac_cfg.h. + * lexer.l: Include config_gram.h instead of y.tab.h. + * lists.c: Include ac_cfg.h. + * main.c: Include ac_cfg.h. + * par.c: Include ac_cfg.h. + * pgm.c: Include ac_cfg.h. + * ppi.c: Include ac_cfg.h. + * stk500.c: Include ac_cfg.h. + * term.c: Include ac_cfg.h. + +2003-02-14 Brian S. Dean + + * stk500.c: Fix typos. Fix error messages. + +2003-02-13 Brian S. Dean + + * Makefile, avrdude.conf.sample, config_gram.y, lexer.l, main.c: + * par.c, par.h, ppi.c, ppi.h, stk500.c: + Split higher level parallel port programmer code off from ppi.c into + its own file par.c, leaving low level parallel port accessor routines + in ppi.c to help with portability. Change the programmer type to + 'PAR' now instead of 'PPI' - 'PAR' represents the parallel port + programmer type. + + Be more liberal with 'static' function declarations within the + programmer implimentation files - these functions should never be + called directly - always use the programmer function references. + + There are still a few places in 'main.c' that directly reference the + parallel programmer explicitly (par_getpinmask). These should be + fixed somehow. + + Axe a few unused functions. + +2003-02-12 Theodore A. Roth + + * .cvsignore: New file. + + * stk500.c: Remove need for inttypes.h. + + * lexer.l: Define YY_NO_UNPUT to quell a compiler warning. + + * Makefile: Remove YACC assignment. + Add '-b y' options to YACC invocation. + Remove leading '-' from 'include .depend'. + +2003-02-12 Joerg Wunsch + + * config_gram.y: + Declare the internally used static functions on top, to get rid of the + compiler warnings. + + Reported by: bison-generated parsers + +2003-02-11 Theodore A. Roth + + * linux_ppdev.h: New file. + * ppi.c: Include system dependant parallel port interface file. + (ppi_open): Add call to ppi_claim(). + (ppi_close): Add call to ppi_release(). + * ppi.h: Define ppi_claim() and ppi_release() as NOPs if not previously + defined. + * stk500.c: Include inttypes header to quell compiler warning. + +2003-02-11 Joerg Wunsch + + * pgm.c, ppi.c, stk500.c: Fix some implicit declaration warnings. + + * config_gram.y: + Move the C declarations to the top of the file. While [b]yacc doesn't + care, bison does, and this is normally the way it's meant to be + anyway. + +2003-02-11 Theodore A. Roth + + * Makefile: Generate dependencies specific to the target system. + Explicitly use byacc. + + * Makefile: + Remove reference to avr-gcc in depend rule (cut & paste error). + +2003-02-09 Brian S. Dean + + * main.c, pgm.c, pgm.h, pindefs.h, ppi.c, ppi.h, stk500.c: + * stk500.h, stk500_private.h, term.c, term.h, CHANGELOG, COPYING: + * Makefile, avr.c, avr.h, avrdude.1, avrdude.conf.sample: + * avrdude.pdf, avrpart.h, config.c, config.h, config_gram.y: + * fileio.c, fileio.h, lexer.l, lists.c, lists.h: + Test commit in new public repository. Before this time this repo + existed on a private system. Commits made by 'bsd' on the old system + were made by Brian Dean (bdean on the current system). + +2003-02-08 Brian S. Dean + + * Makefile, avr.c, avr.h, avrdude.1, avrpart.h, config.c, + * config.h, config_gram.y, fileio.c, fileio.h, lexer.l, lists.c: + * lists.h, main.c, pgm.c, pgm.h, pindefs.h, ppi.c, ppi.h: + * stk500.c, stk500.h, term.c, term.h: + The last part of that last commit message should read: + + All others - modify program description. + + * Makefile, avr.c, avr.h, avrdude.1, avrpart.h, config.c: + * config.h, config_gram.y, fileio.c, fileio.h, lexer.l, lists.c: + * lists.h, main.c, pgm.c, pgm.h, pindefs.h, ppi.c, ppi.h: + * stk500.c, stk500.h, term.c, term.h: + Makefile: include a target to automatically generate the dependency + list. + + All others + +2003-02-06 Brian S. Dean + + * avrdude.1: Update license to GPL, permission by Joerg Wunsch. + + * lexer.l: Add GPL. + + * Makefile, config_gram.y: Add GPL to the Makefile and config_gram.y. + + * Makefile, stk500.h: + Add stk500.h as a dependency for stk500.c. Remove carraige returns + from stk500.h - don't know how those got in there (pointed out by Ted + Roth). + + * COPYING, avr.c, avr.h, avrpart.h, config.c, config.h, fileio.c: + * fileio.h, lists.c, lists.h, main.c, pgm.c, pgm.h, pindefs.h: + * ppi.c, ppi.h, stk500.c, stk500.h, term.c, term.h: + Re-license using the GNU GPL. Thanks to Ted Roth for the patch. + + * avr.c, avr.h, config.c, config.h, config_gram.y, fileio.c: + * fileio.h, lexer.l, lists.c, lists.h, main.c, pgm.c, pgm.h: + * pindefs.h, ppi.c, ppi.h, stk500.c, stk500.h, term.c, term.h: + Get rid of the verbose printing of individual file CVS version ids. + This was intended to be used for identifying code in the field for + incoming bug reports, but I've never really found it all that useful. + + * CHANGELOG, Makefile, Makefile.inc, avr.c, avrdude.1: + * avrdude.conf.sample, config_gram.y, lexer.l, main.c, stk500.c: + * term.c: + Change the name from AVRPROG to AVRDUDE. + + This change represents a name change only. There is currently an + effort to port AVRPROG to other platforms including Linux and Windows. + Since Atmel's programmer binary that's included within their AVR + Studio software is named AVRPROG.EXE on the Windows OS, there is the + chance for confusion if we keep calling this program AVRPROG as well. + Up until now the name hasn't really been a problem since there was no + chance to confuse 'avrprog' on Unix with Atmel's AVRPROG because + Atmel's tools only run on Windows. But with the Unix 'avrprog' + possibly being ported to Windows, I felt a name change was the best + way to avoid problems. + + So - from this point forward, my FreeBSD Unix program formerly + known as AVRPROG will subsequently be known as AVRDUDE (AVR + Downloader/UploaDEr). + + This change also represents a time when the AVRDUDE sources move from + my own private repository to a public repository. This will give + other developers a chance to port AVRDUDE to other platforms and + extend its functionality to support additional programming hardware, + etc. + + So goodbye AVRPROG, welcome AVRDUDE! diff --git a/avrdude/ChangeLog-2004-2006 b/avrdude/ChangeLog-2004-2006 new file mode 100644 index 00000000..20e5b2e8 --- /dev/null +++ b/avrdude/ChangeLog-2004-2006 @@ -0,0 +1,1644 @@ +2006-12-23 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version to 5.3cvs (again). + +2006-12-22 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version to 5.3.1. + * avrdude.conf.in (frank-stk200): Fix syntax error. + * ser_avrdoper.c: Make #ifdef for Win32/libhid + consistent with the initial check: use the HID driver + only iff found, otherwise use libusb. + +2006-12-21 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version to 5.3cvs. + +2006-12-21 Joerg Wunsch + + Released AVRDUDE 5.3. + +2006-12-21 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version to 5.3. + +2006-12-21 Joerg Wunsch + + Submitted by Vince VG: + * avrdude.conf.in (frank-stk200): New programmer added. + * doc/avrdude.texi: Mention frank-stk200. + Closes patch #5502: one other programmer + +2006-12-21 Joerg Wunsch + + Submitted by Christian Starkjohann: + * ser_avrdoper.c (usbOpenDevice): clear the error code when + returning successfully. + +2006-12-21 Joerg Wunsch + + Submitted by Christian Starkjohann: + patch #5507: Support for AVR-Doper USB programmer in HID mode + * configure.ac: Add hooks to detect the Win32 HID library, + as well as the existence of . + * Makefile.am: Add new files. + * my_ddk_hidsdi.h: (New file.) + * ser_avrdoper.c: (New file.) + * serial.h: Add declaration for avrdoper_serdev. + * stk500v2.c: Add hook to divert to the AVR Doper code. + * avrdude.1: Document the AVR Doper support. + * doc/avrdude.texi: (Ditto.) + +2006-12-15 Joerg Wunsch + + Submitted by ivanv at netman.ru + * jtagmkI.c: fix length for single-byte write operations. + Closes bug #18527 JTAG ICE: fuse bits have been writen incorrectly + +2006-12-11 Joerg Wunsch + + * jtagmkII.c (jtagmkII_paged_write): Remove a debugging + usleep(1000000) that accidentally crept in in rev 1.19. + +2006-12-11 Joerg Wunsch + + * ser_posix.c (ser_open): Do fill in fdp->ifd before already + using it in ser_setspeed(). + +2006-12-11 Joerg Wunsch + + * jtagmkI.c (jtagmkI_close): revert baud rate to the initial + value in case we had changed it. + Fixes bug #18262: JTAGMKI/JTAG1 Reset Bug + +2006-12-11 Colin O'Flynn + + * safemode.c: Stop ignoring return values! + Closes bug #18339 + +2006-12-11 Joerg Wunsch + + Submitted by Nick Lott: + * avrdude.conf.in: Fix signature for ATmega8515. + Closes bug #18348: ATMEGA8515 Signature is wrong in avrdude.conf + +2006-12-11 Joerg Wunsch + + * avr.c: Fix a bug introduced in rev. 1.69, when implementing the + fallback from each programmer's paged_load() or paged_write() + method, respectively. The return value needs to be checked for + being greater or equal than 0 rather equal to 0 in order to + assume the operation has been successful. + Fixes bug #18489: avrdude is too slow (20 byte/s) + +2006-12-11 Joerg Wunsch + + * avr910.c: Make the code compile warning-free: + - declare a dummy "struct timezone" for some Win32 systems (MinGW) + - fix a few printf() argument types + - get rid off the prevailing "all filedescriptors are of type int" + attitude + The last item required a large sweep across the code, in order to + replace all "int fd"s by "struct filedescriptor *fd"s, and pass + pointers (as we cannot pass a union directly). In return, the + code is now supposed to be fully 64-bit safe, rather than relying + on a 64-bit pointer being converted to a (32-bit) int and back + to a pointer as we did previously. + * butterfly.c: (Ditto.) + * jtagmkI.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * lists.c: (Ditto.) + * par.c: (Ditto.) + * pgm.h: (Ditto.) + * ppi.c: (Ditto.) + * ppi.h: (Ditto.) + * ppiwin.c: (Ditto.) + * ser_posix.c: (Ditto.) + * ser_win32.c: (Ditto.) + * serbb_posix.c: (Ditto.) + * serbb_win32.c: (Ditto.) + * serial.h: (Ditto.) + * stk500.c: (Ditto.) + * stk500v2.c: (Ditto.) + * usb_libusb.c: (Ditto.) + +2006-11-23 Joerg Wunsch + + Implement EEPROM access through debugWire. + * jtagmkII.c: Extend the jtagmkII_read_byte() and + jtagmkII_write_byte() methods to handle EEPROM through + debugWire. + * avrpart.h: Implement the "flash instruction" parameter. + * config_gram.y: (Ditto.) + * lexer.l: (Ditto.) + * avrdude.conf.in: (Ditto.) + * avrdude.1: Document the EEPROM access through dW. + * doc/avrdude.texi: (Ditto.) + * tools/get-dw-params.xsl: Extend to extract the flash + instruction field. + +2006-11-23 Joerg Wunsch + + * avr.c (avr_read, avr_write): if the paged access returns a + failure, fall back to byte access. + +2006-11-21 Joerg Wunsch + + * jtagmkII.c: In jtagmkII_read_byte() and jtagmkII_write_byte(), + return an error upon failure now that the upper layers won't fall + back to the cmd() method anymore in that case. + +2006-11-21 Joerg Wunsch + + Implement debugWire programming support. + * avrpart.h: Implement debugWire support. + * config_gram.y: (Ditto.) + * jtagmkII.c: (Ditto.) + * jtagmkII.h: (Ditto.) + * lexer.l: (Ditto.) + * avrdude.conf.in: Add the new dW programmers. + * avrdude.1: Document the dW support. + * doc/avrdude.texi: (Ditto.) + * tools/get-dw-params.xsl: XSL stylesheet to extract the dW + parameters from the XML files. + +2006-11-20 Joerg Wunsch + + * jtagmkI.c (jtagmkI_close): remove two unused variables. + +2006-11-20 Joerg Wunsch + + * avr.c: Replace the fallback of avr_read_byte() and avr_write_byte() to + avr_read_byte_default() and avr_write_byte_default (resp.) by directly + calling the latter functions from within all programmers that don't + implement their own read_byte()/write_byte() methods. In turn, make the + read_byte() and write_byte() methods mandatory, and the cmd() method + (direct ISP command) optional instead (it's effectively mandatory for + any programmer using avr_read_byte_default()/avr_write_byte_default() + though). Remove all the pointless cmd() method stubs from those programmers + that don't need it. + Eliminate avr_read_byte() as it was now completely identical to + pgm->read_byte(). + * avr.h: (Ditto.) + * bitbang.c: (Ditto.) + * butterfly.c: (Ditto.) + * jtagmkI.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * par.c: (Ditto.) + * pgm.c: (Ditto.) + * safemode.c: (Ditto.) + * serbb_posix.c: (Ditto.) + * serbb_win32.c: (Ditto.) + * stk500.c: (Ditto.) + * stk500v2.c: (Ditto.) + * term.c: (Ditto.) + * usbasp.c: (Ditto.) + +2006-11-13 Joerg Wunsch + + * jtagmkI.c: Avoid sending a CMD_RESET when leaving programming + mode, and CMD_GO when closing the connection. They cause the + activity LED on the ICE to continue to flicker, and are not + necessary anyway (the target starts to run by itself when leaving + programmng mode). + This is a partial fix for bug #18262: JTAGMKI/JTAG1 Reset Bug + +2006-11-12 Colin O'Flunn + + * avrdude.conf.in: Add read command for lockbits for Tiny2313. + Applies patch #5538 + +2006-11-10 Joerg Wunsch + + * avrdude.conf.in: Add signatures for ATmega325/3250/645/6450. + +2006-11-08 Joerg Wunsch + + * configure.ac: Preserve ${LDFLAGS} inherited from environment + for Win32 environments. + +2006-11-07 Joerg Wunsch + + * configure.ac: Don't pretend --enable-doc were the default. + +2006-11-02 Joerg Wunsch + + * avrdude.conf.in: Fix the width of the efuse memory area for a + number of AVRs. + Closes bug #18182: Wrong setting of eFuse configuration for + mega640/1280/1281/2560/2561 in avrdude 5.2 + +2006-11-01 Joerg Wunsch + + * avrdude.conf.in: Implement HVSP and PP modes for the AVR Dragon. + * config_gram.y: (Ditto.) + * jtagmkII.c: (Ditto.) + * jtagmkII_private.h: (Ditto.) + * lexer.l: (Ditto.) + * stk500v2.c: (Ditto.) + * stk500v2.h: (Ditto.) + * avrdude.1: Document the HVSP and PP support for the Dragon. + * doc/avrdude.texi: (Ditto.) + +2006-10-27 Joerg Wunsch + + * jtagmkI.c: Implement a flags field in struct serdev, and populate it + with a flag that indicates whether the underlying communication can + dynamically change its speed or not. This flag is set for true serial + communication but clear for USB communication. Don't try to adjust + the speed when talking over a communication channel that doesn't + support it. (The Dragon does not even support the respective parameter.) + * jtagmkII.c: (Ditto.) + * ser_posix.c: (Ditto.) + * ser_win32.c: (Ditto.) + * serial.h: (Ditto.) + * usb_libusb.c: (Ditto.) + +2006-10-26 Joerg Wunsch + + * avrdude.conf.in: Add support for the AVR Dragon (JTAG and ISP mode). + * config_gram.y: (Ditto.) + * jtagmkII.c: (Ditto.) + * jtagmkII.h: (Ditto.) + * lexer.l: (Ditto.) + * stk500v2.c: (Ditto.) + * stk500v2.h: (Ditto.) + * usbdevs.h: (Ditto.) + * avrdude.1: Document the AVR Dragon support. + * doc/avrdude.texi: (Ditto.) + +2006-10-09 Joerg Wunsch + + Released AVRDUDE 5.2. + +2006-10-09 Joerg Wunsch + + * configure.ac: Bump version to 5.2 + +2006-10-09 Joerg Wunsch + + Submitted by John Voltz: add AVR053 oscillator calibration. + * main.c: Add the -O option. + * pgm.c: Add the hook for the perform_osccal() method. + * pgm.h: (Ditto.) + * stk500v2.c: Implement perform_osccal(). + * avrdude.1: Document the -O option. + * doc/avrdude.texi: (Ditto.) + Partially closes bug #17487: AVR RC oscillator calibration + routine not supported (feature request) + +2006-10-09 Joerg Wunsch + + Submitted by freckle@sf.net: + * stk500.c (stk500_paged_write): Send the command and the data + payload within a single write(). + patch #5025: Improve stk500.c robustness + + Submitted by Matthias Ringwald: + * stk500.c (stk500_open): do not flush the serial line after + getting in sync with the programmer. + patch #5293: stk500.c: no drain after sync (-> allow BTnode + Bootloader to work on cygwin) + +2006-09-29 Joerg Wunsch + + * pgm.h: Fix prototype for gettimeofday(). + Closes bug #17884: another gettimeofday conflict under win32/cygwin + +2006-09-24 Joerg Wunsch + + Submitted by Thomas Fischl (initially): + * configure.ac: Add the CoreFoundation and IOKit framework + linker flags on MacOS X when configuring for USB support. + patch #4685: Libusb on MacOS X: detection and additional includes + +2006-09-20 Joerg Wunsch + + * avr910.c: As there is a lot of ambiguity about the AVR910 + device codes, allow the user to override the device code + verification with the -F option. + * main.c: Make ovsigck a global variable. + +2006-09-20 Joerg Wunsch + + Add the "stk500generic" programmer that auto-probes for STK500 + either firmware version 1 or 2. + * Makefile.am (avrdude_SOURCES): add the new files + stk500generic.c and stk500generic.h. + * avrdude.conf.in: Add the stk500generic programmer type, and + change the "stk500" entry to point to this programmer. + * config_gram.y: Add the stk500generic keyword. + * lexer.l: (Ditto.) + * stk500.c: Change the stk500v1 code to not call exit() + prematurely when failing to open the programmer, but instead + return an error status. + * stk500generic.c: (New file.) Stub programmer implementation. + Probe for either stk500v1 or stk500v2, and adjust the current pgm + appropriately. + * stk500generic.h: (New file.) Declare the public interface(s) + of stk500generic.c. + * doc/avrdude.texi: Document the changed behaviour of stk500. + +2006-09-18 Joerg Wunsch + + * avrdude.conf.in: Various fixes for ancient processors and their + capabilities. For the AT90S1200 and the AT90S8515, fuse bit + handling via ISP, and lock bit reading via ISP are not supported + at all. For the AT90S4414 (small brother of the AT90S8515), add + the ability to write the lock bits, and add a definition for the + fuse bits (usable for HV programming). For the AT90S2313, add the + "fuse" memory range, so it's available for HV programming. + + Resolves bug #17796: avrdude will not program or verify lockbits + with Atmel STK protocol programmers + +2006-09-17 Joerg Wunsch + + Submitted by Thomas Fischl: + * usbasp.c: Check for USBasp with new as well as old VID/PID + pair, warn the user about upgrading the firmware in case an + old one has been found. + * usbasp.h: Add new VID/PID. + +2006-09-15 Joerg Wunsch + + * avrdude.conf.in: Fix some mistakes for the ATtinyX61 family: + . high fuse has 8 bits + . there is an extended fuse (just one bit) + . the calibration area is only 1 byte + +2006-09-12 Joerg Wunsch + + * doc/avrdude.texi: Convert some of the tables to multitables + in order to beautify the result. + +2006-09-10 Joerg Wunsch + + Contributed by Thomas Fischl: add support for USBasp. + patch #4686: Add support for USBasp, a simple USB programmer + * usbasp.c: New file, implement the USBasp driver. + * usbasp.h: New file, interface declarations for USBasp. + * Makefile.am: Wire the new files into the build. + * avrdude.conf.in: Add the usbasp programmer entry. + * config_gram.y: Add the usbasp token. + * lexer.l: (Ditto.) + * avrdude.1: Document the USBasp programmer. + * doc/avrdude.texi: (Ditto.) + +2006-09-08 Joerg Wunsch + + * main.c: Implement -U filename as a shorthand for + -U flash:w:filename:a. + * avrdude.1: Document this. + * doc/avrdude.texi: (Ditto.) + +2006-09-08 Joerg Wunsch + + Implement numerical output formats for decimal, hexadecimal, + octal, and binary numbers. + Closes bug #16129: more output formats for fuse bits + (avrdude enhancement request) + * fileio.c: Implement fileio_num() and the itoa_simple() + helper function. + * fileio.h: Add new file formats to FILEFMT. + * main.c: Parse the new file formats. + * avrdude.1: Document all this. + * doc/avrdude.texi: (Ditto.) + +2006-09-08 Joerg Wunsch + + * fileio.c: CPP statements start in column #1. + * stk500v2.c: Hide two debug/trace statements behind "verbose". + +2006-09-07 Joerg Wunsch + + * avrdude.1: Describe how to disable the DWEN fuse. + * doc/avrdude.texi: (Ditto.) + +2006-09-07 Joerg Wunsch + + * jtagmkII.c: Translate numerical response codes to strings. + +2006-09-07 Joerg Wunsch + + * avrdude.1: The avr109 programmer type no longer chokes on + a wrong avr910 device ID, so remove that description. + * doc/avrdude.texi: (Ditto.) + +2006-09-07 Joerg Wunsch + + * jtagmkII.c: When failing to start in ISP mode, try + debugWire instead. This requires the user to eventually + restart AVRDUE from scratch then. + +2006-09-06 Joerg Wunsch + + Add support for the JTAG ICE mkII in ISP mode. + * avrdude.conf.in (jtag2isp): New programmer entry. + * config_gram.y: Add K_JTAG_MKII_ISP. + * jtagmkII.c: Restructure and export some more functions. + * jtagmkII.h: Declare exported functions. + * jtagmkII_private.h: Prepare file to be included in stk500v2.c. + * lexer.l: Add jtagmkii_isp token. + * stk500v2.c: Implement glue to jtagmkII.c. + * stk500v2.h: Declare stk500v2_jtagmkII_initpgm(). + * avrdude.1: Document the new programmer support. + * doc/avrdude.texi: (Ditto.) + +2006-09-01 Joerg Wunsch + + * main.c: Add date and time of compilation to the verbose + greeting message. + Idea taken from patch #3172: Adds date and time of compile + to usage message + +2006-09-01 Joerg Wunsch + + Contributed by as + patch #4372: Better synchronization for stk500 + * stk500.c: Sync three times, and drop any noise inbetween. + +2006-09-01 Joerg Wunsch + + * avrdude.conf.in (ATtiny261, ATtiny461, ATtiny861): new + entries. + +2006-09-01 Joerg Wunsch + + * butterfly.c: Remove the device support decision based on + the old AVR910 device codes; we've got signature verification + now so better rely on that. + * avr910.c: Revert the signature bytes returned, as it already + happened in butterfly.c. This closes bug #14998: Signature Bytes + read in wrong order (avr910 mode) + +2006-09-01 Joerg Wunsch + + Submitted by Wim Lewis. + * serbb_posix.c: Improve error handling. + patch #4923: Better error reporting for serial-bitbang programmers + +2006-08-31 Joerg Wunsch + + * avrdude.conf.in: Introduce a "stk500v1" entry, so we + can switch the default "stk500" to "stk500v2" some day. + +2006-08-31 Joerg Wunsch + + The major part of this change has been contributed by + . + Implements patch #4635: Add support for terminal/console + servers for serial programmers + * ser_posix.c: Add net_open(), and divert to it for net:host:port. + * ser_win32.c: Recognize net:host:port, and bail out. + * avrdude.1: Document the net:host:port connection option. + * doc/avrdude.texi: (Ditto.) + +2006-08-31 Joerg Wunsch + + Fix for bug #16627: Butterfly programmer does not reset after + programming + * butterfly.c: Wait for the device's response after sending + an "E" command. + +2006-08-31 Joerg Wunsch + + Tentative fix for bug #16156: Problem with Si-Prog + * serbb_posix.c: Disable reset before closing. + * serbb_win32.c: (Ditto.) + +2006-08-30 Joerg Wunsch + + Rewrite the serbb code so the pin numbering matches the + DB9 connector, and fix some related bugs in serbb_posix.c. + Closes bug #16265: dasa2 does not work under posix + * avrdude.conf.in: New serbb pin numbering; added "siprog" + as an alias for "ponyser". + * serbb_posix.c: New pin numbering, fix some confusion. + * serbb_win32.c: New pin numbering. + The generic and Posix-related parts of these changes have + been contributed by Hanns-Konrad Unger + +2006-08-30 Joerg Wunsch + + Contributed by the anonymous developer of patch #5096: + * avrdude.conf.in (blaster): Add an entry for the Altera + byteblaster. + +2006-08-30 Joerg Wunsch + + Rework the exit specs so they actually work again. It should be + possible to extend them for other programmers than PPI now (serbb, + stk500*). + * pgm.h: Keep the exit specs in an abstract form inside struct + programmer_t. (Should be moved out into some programmer-specific + structure.) Rename the getexitspecs() method into + parseexitspecs(). + * main.c: Move the exit specs stuff out to the programmer + implementation. + * par.c: Implement the new exit spec handling. Everything is now + done using the generic abstraction layer. + Closes bug #16443: No disable Resetsignal at the end of + Programming Session + Obviates need for patch #5057: quick and dirty Hack to unset Reset + after Programming + +2006-08-29 Joerg Wunsch + + This patch has been contributed by an anonymous developer + via the patch tracking system. + patch #5096: Allow VCC and BUFF to be any pin in parallel mode + * config_gram.y: Release the restriction to PPIDATA pins. + * par.c: Rework the code to introduce a function par_setmany() + that builds on top of par_setpin(), and use that function for the + PPI_AVR_VCC and PPI_AVR_BUFF pin collections. This also abstracts + the polarity of these signals appropriately. + +2006-08-28 Joerg Wunsch + + Contributed by Ned Konz: + * ser_posix.c: Open the serial port with O_NONBLOCK, and + save and restore the port state before exiting. + patch #5008: Patch for (5.1) ser_posix.c for O_NONBLOCK open + and restoring serial port state on close + Closes bug #12622: avrdude hangs on macosx/darwin with PL-2303 + usb-to-serial and Butterfly + +2006-08-22 Joerg Wunsch + + * bitbang.c: Move the bitbang prerequisite checks out from + main() into their own bitbang_check_prerequisites(). + * bitbang.h: (Ditto.) + * main.c: (Ditto.) + * par.c: (Ditto.) + * serbb_posix.c: (Ditto.) + * serbb_win32.c: (Ditto.) + +2006-08-22 Joerg Wunsch + + * avrdude.conf.in: Add page mode parameters for all "eeprom" + memory definitions that are organized in pages. + * avr.c (avr_write_byte_default): Consider using the loadpage + instructions only if the respective memory is marked "paged". + Closes bug #17199: EEPROM fails verification on ATmega645 with + pony-stk200 hardware + Closes bug #16849: EEPROM write fails for AT90USB1287 with + mode 0x41 + Closes bug #15146: stk500v2_paged_write: loadpage instruction + not defined for part + +2006-08-22 Joerg Wunsch + + * doc/avrdude.info (-c): Change "avrispmk2" into "avrisp2" as that + is the programmer actually supported by avrdude.conf.in. + Closes bug #15677: documentation mentions wrong programmer-id + "avrispmk2" + +2006-08-21 Joerg Wunsch + + * avrdude.conf.in: Fix various AVR910 device codes. Add the code + tables from both, AVR910 and AVR109. Change avr910_devcode of + the ATtiny2313 to 0x5e (ATtiny26). + Closes bug #16671: Tiny2313 avr910_devcode is bad + Closes bug #15826: avr910 device type for ATmega8 wrong + +2006-08-21 Joerg Wunsch + + * avrdude.conf.in: Add (rather conservative) write delay timing + values to the *fuse and lock memory spaces of all devices where + they have been missing. Add the lock memory space to the ATmega48 + section. + Closes bug #14920: tiny2313 fuses and AVRDUDE 5.0 + Closes bug #15751: atmega48: no lock bits defined + +2006-08-21 Joerg Wunsch + + * avrdude.conf.in: Fix the size of the calibration memory space + for ATtiny13, ATmega64, ATmega16, ATmega32, ATmega8535, ATtiny25, + ATtiny45, ATtiny85. + Closes bug #17383: Wrong calibration section in avrdude.conf... + +2006-08-21 Joerg Wunsch + + * avrdude.conf.in (ATmega324): Correct the pagesize from 256 to + 128. + This closes bug #16410: ATMega164/324/644 cannot be programmed + +2006-08-20 Joerg Wunsch + + * configure.ac: Check for gettimeofday(). + * ppiwin.c (gettimeofday): Define gettimeofday() replacement + only if !defined(HAVE_GETTIMEOFDAY); use correct protype. + +2006-08-18 Joerg Wunsch + + * stk500v2: Minor cosmetic changes: STK500 firmware version + numbers are M.NN, so always display the minor number as two + digits. Examine the response to the sign-on command to see which + programmer hardware we are talking to, and then restrict the + STK500 topcard display to devices detected as STK500. + +2006-08-18 Joerg Wunsch + + * Makefile.am: Add a dist-hook, and make it remove lexer.c, + config_gram.c, and config_gram.h from the source distribution + archive. These files are supposed to be generated on the target + system. + Closes bug #15536: avrdude-5.1 compilation fails on Gentoo/amd64 + +2006-08-17 Joerg Wunsch + + * stk500v2.c: unreverse the argument order for + CMD_CHIP_ERASE_HVSP; Atmel says AVR068 is right, and + stk500.exe is wrong. + * configure.ac (AC_CHECK_LIB[usb]): Fix the generation + of HAVE_LIBUSB in ac_cfg.h. + +2006-08-17 Joerg Wunsch + + Submitted by Neil Davey: + patch #4539: Ability to control the bit clock (usleep) delay + for ppi interface + * bitbang.c: Implement bitbang_delay() and its calibration. + * bitbang.h: Declare bitbang_delay(). + * main.c: Add the ispdelay option (-i). + * pgm.h (struct programmer_t): Add the ispdelay parameter. + * par.c: Add calls to bitbang_delay() when requested. + * serbb_posix.c: (Ditto.) + * serbb_win32.c: (Ditto.) + * avrdude.1: Document the new -i option. + * doc/avrdude.texi: (Ditto.) + +2006-08-14 Joerg Wunsch + + Submitted by : + * avrdude.conf.in (ATmega48, ATmega88, ATmega168): patch #5100: + mega88 EEPROM support (extended for ATmega48 and ATmega168 - jw). + +2006-08-14 Joerg Wunsch + + Submitted by : + * stk500v2.c (stk500v2_open): patch #5273: Emit error message + if user requests usb and no libusb support + +2006-08-14 Joerg Wunsch + + * avrdude.conf.in: Add HVSP/PP mode parameters for all AVRs. + +2006-08-13 Joerg Wunsch + + * tools: New directory. + * tools/get-hv-params.xsl: New file, extract high-voltage + programming parameters from Atmel XML files, and produce + an avrdude.conf[.in] snippet. + +2006-08-11 Joerg Wunsch + + * configure.ac (AC_CHECK_LIB([usb]): implement a private LIBUSB + macro to add this library to, to prevent it from being + automatically linked to all binaries. This should fix the Win32 + build of loaddrv. + * Makefile.am (avrdude_LDADD): add LIBUSB here. + +2006-08-10 Eric B. Weddington + + Contributed by Bob Paddock + * avrdude.conf.in: Patch #4780. Provide support for mega325, + mega3250, mega645, mega6450. + +2006-08-10 Joerg Wunsch + + * avrdude.conf.in (ATtiny11): fix the HVSP control stack, + add delay values required for flash and EEPROM. + * stk500v2.c: reverse the argument order for + CMD_CHIP_ERASE_HVSP; AVR068 and stk500.exe differ here. + +2006-08-09 Joerg Wunsch + + * stk500v2.c (stk500v2_program_enable): Fix a typo + (synchloops vs. synchcycles). + +2006-08-04 Joerg Wunsch + + * avrdude.conf.in: Add parallel programming definitions for + the ATmega8/48/88/168. + +2006-07-22 Joerg Wunsch + + * avrdude.conf.in: Add the ATtiny11, an HVSP-only device. + +2006-07-21 Joerg Wunsch + + Implement STK500 (v2) HVSP mode. + * stk500v2.c: Add new functions for HVSP support. + * stk500v2.h: Add prototype for the stk500hvsp programmer. + * avrpart.h: Add fields to struct avrpart for new features. + * config_gram.y: Extend the configuration syntax for new + features required for HVSP support. + * lexer.l: (Ditto.) + * avrdude.conf.in: Add HVSP support for ATtiny13 and + ATtiny45 as an example. + * avrdude.1: Document stk500hvsp. + * doc/avrdude.texi: (Ditto.) + +2006-07-21 Joerg Wunsch + + * avrpart.c: Print the very verbose memory details only + in debug level > 4. + +2006-07-19 Joerg Wunsch + + * stk500v2.c: Add more parameters for PP mode. Fix the + non-paged write operations for old AVRs. + * lexer.l: Add more parameters for PP mode. + * config_gram.y: (Ditto.) + * avrpart.h: (Ditto.) + * avrdude.conf.in: Use the new PP mode parameters; add PP mode + definitions for AT90S8515. + * avrdude.1: Document the stk500pp support. + * doc/avrdude.texi: (Ditto.) + +2006-07-19 Joerg Wunsch + + * stk500v2.c: Hide stk500v2_set_sck_period_mk2() behind an #if + defined(HAVE_LIBUSB) as it is only used there (for the AVRISP + mkII). + +2006-07-17 Joerg Wunsch + + * stk500v2.c: Fix all bugs in stk500pp. Eliminate pagebuf, and + use a stack-allocated buffer instead, as the pagesize can be at + most 256 for all current AVRs anyway. + +2006-07-17 Joerg Wunsch + + * main.c: Use mem->desc in place of upd->memtype in more places to + give the full name of the respective memory area, instead of + the (possibly abbreviated) name the user typed in the -U option. + +2006-07-16 Joerg Wunsch + + First stab at an implementation of the STK500 parallel programming + feature (v2 firmware only), named "stk500pp". Still not yet + complete: EEPROM writes not working, documentation missing, only + ATmega16 parameters available in avrdude.conf.in, some parameters + not yet implemented. + * avrdude.conf.in: Add sample parameters for PP mode to ATmega16. + * avrpart.h: Add the parallel programming control parameters. + * avrpart.c: (Ditto.) + * config_gram.y: Add stk500pp configuration grammar. + * lexer.l: Add stk500pp token recognition. + * stk500v2.h: Add declaration for stk500pp_initpgm(). + * stk500v2.c: Add stk500pp implementation. + +2006-07-11 Joerg Wunsch + + * avrdude.conf.in: Fix the signatures for the + ATmega164/324 devices. + +2006-07-10 Joerg Wunsch + + * avrdude.conf.in: Enter the signatures for the + ATmega164/324/644 devices. + +2006-05-25 Joerg Wunsch + + * stk500v2.c: Implement extended addressing needed + for the ATmega256x devices. + * avrdude.1: Document ATmega256x support. + * doc/avrdude.texi: Document ATmega256x support. + Also document Solaris port defaults. + +2006-05-24 Joerg Wunsch + + * avr.c: Start implementing support for ATmega256x; + jtag2 and bitbang programmers are working, stk500v2 + still needs to be done. + * avrdude.conf.in: (Ditto.) + * avrpart.c: (Ditto.) + * avrpart.h: (Ditto.) + * config_gram.y: (Ditto.) + * lexer.l: (Ditto.) + +2006-04-18 Joerg Wunsch + + Contributed by Julius Luukko : + * avrdude.conf.in: Add the "ere-isp-avr" programmer. + +2006-04-13 Joerg Wunsch + + * par.c: Add logic to negate parallel-port signals in + avrdude.conf using a tilde. + + Contributed by Bram Daams: + * avrdude.conf.in: Add the "atisp" programmer entry that + makes use of negated signals. + +2006-03-28 Joerg Wunsch + + * avrdude.conf.in: Add entries for AT90USB{64,128}{6,7} + +2006-03-23 Colin O'Flynn + + Contributed by Wim Lewis, fix a few typos (patch #4987) + * avrdude.1: Typo fix + +2006-02-27 Colin O'Flynn + + Contributed by Wim Lewis, add support for checking device + signatures in detail (patch #4924 and #4925) + * avrdude.conf.in: Add signatures + * avrpart.c: Set default signature + * avrpart.h: Variable for signature + * config_gram.y: More signature reading + * lexer.l: Define that signatures exist + * main.c: Read signatures and check them against hardware + +2006-02-21 Joerg Wunsch + + * avrdude.conf.in: Fix paged flash write for AT90PWMx + (error in datasheet). + +2006-01-23 Joerg Wunsch + + * configure.in: Bump version. + +2006-01-17 Colin O'Flynn + + * main.c: Fixed a typo in safemode variable names, fixed bug 15113 + * avrdude.conf.in : Added BS2 and pagel to M162, Patch 4766 + * main.c, stk500v2.c: Added patch 4804 from eolson@mit.edu + Which stops sck from being writtend needlessly + +2006-01-13 Joerg Wunsch + + Contributed by David Moore: add support for the + AVRISP mkII device. (Savannah patch #4789.) + * serial.h: Declare usb_serdev_frame device descriptor. + * stk500v2.c: Implementation of the AVRISP mkII handling. + * usb_libusb.c: Add USB handling for short-frame delimited + AVRISP mkII USB protocol; add distinction of different + devices in usbdev_open(). + * jtagmkII.c: Tell usbdev_open() to search for the JTAG ICE mkII. + * usbdevs.h: (New file.) + * Makefile.am: Add usbdevs.h, as well as some other forgotten + files "make distcheck" complained about. + * avrdude.conf.in: Add more aliases for the AVRISP mkII. + * avrdude.1: Document how to use the AVRISP mkII. + * doc/avrdude.texi: (Ditto.) + +2006-01-12 Joerg Wunsch + + * avrdude.conf.in: Add EEPROM page instructions for the + ATmega169 so it will work for STK500v2. + +2005-12-16 Joerg Wunsch + + * avrdude.conf.in: Added support for ATtiny24/44/84. + +2005-12-05 Colin O'Flynn + + * avrdude.conf.in: Added m162 support for stk500v2 + +2005-12-01 Joerg Wunsch + + * avrdude.conf.in: fix the number of significant bits for + the efuse memory in ATmega48/88/168; the datasheet is a bit + off here as well. + +2005-11-29 Joerg Wunsch + + * avrdude.1: update for JTAG ICE mkI support. + * doc/avrdude.texi: (Ditto.) + +2005-11-29 Joerg Wunsch + + Submitted by Galen Seitz: + patch #4459: Fix for rpm package builds + * avrdude.spec.in: update the RPM spec file: + - Default to enable-doc=yes during configure. + - Move info file to docs package. + - Make building of docs package conditional. Basic + idea copied from avr-gcc. + +2005-11-29 Joerg Wunsch + + Submitted by someone who thinks he's called "Daper": + Fix bug #15013: Wrong use of PPICLAIM (kernel: ppdev0: claim the + port first) + * par.c: don't claim/release here (thus win_ppdev.h not needed + anymore) + * ppi.c: claim/release here. + * freebsd_ppi.h: ppi_claim/ppi_release now take an fd as parameter. + * solaris_ecpp.h: (Ditto.) + * linux_ppdev.h: (Ditto.) (Also add copyright.) + * win_ppdev.h: Not needed anymore, remove. + +2005-11-28 Joerg Wunsch + + * jtagmkI.c: Improve the communication startup with the ICE. + +2005-11-28 Joerg Wunsch + + * configure.ac: enable parport access on x86_64 Linux and + FreeBSD systems. + +2005-11-27 Joerg Wunsch + + * avrdude.conf.in: add the "calibration" space to ATmega16. + +2005-11-25 Colin O'Flynn + + Fixed bug 15051, building for Windows breaks. + * par.c: ppi_claim and ppi_release definitions now in a Windows header file + * ppi.c: Only included if you are building for Windows + * win_ppdev.h: Initial Commit, see par.c + +2005-11-24 Joerg Wunsch + + Add basic support for the Atmel JTAG ICE mkI: + * config_gram.y: add mkI support to config sytax. + * lexer.l: (Ditto.) + * avrdude.conf.in: add sample programmer entries. + * jtagmkI.c: New file + * jtagmkI.h: New file + * jtagmkI_private.h: New file + * Makefile.am: include new files in build. + +2005-11-24 Colin O'Flynn + + Fix bug 14681 - Serial Communication Fails on -vvvv with Windows + * ser_win32.c: Patched with Brian Dean's patch + +2005-11-05 Colin O'Flynn + + Patch #4532 by Manfred Bartz + * avrdude.conf.in: added support for ATMega168 (also added support + for the stk500v2 protocol which was not in the patch). + +2005-11-03 Joerg Wunsch + + Add ecpp(7D) (parallel port) for Solaris. + * configure.ac: add Solaris' default parallel port. + * linux_ppdev.h: change parallel port access to the new style. + * freebsd_ppi.h: New file, abstract FreeBSD's ppi(4). + * solaris_ecpp.h: New file, abstract Solaris' ecpp(7D). + * par.c: change header inclusion sequence. + * pgm.h: remove obsolete ppi_claim() and ppi_release() dummies. + * ppi.c: change header inclusion sequence, use new parport + abstraction, drop obsolete dummy implementation. + +2005-11-02 Joerg Wunsch + + * config.h: change YYSTYPE to be a single word, to work around + a bug in Solaris' yacc. + * lexer.l: remove incompatibilities with Solaris' default lex, + bump resource limits for lex. + +2005-11-01 Joerg Wunsch + + Make avrdude Solaris-compatible. + * Makefile.am: distclean avrdude.conf. + * avrdude.conf.in: make the parallel-port programmers optional. + * bitbang.c: move the bitbang features out into PROGRAMMER. + * configure.ac: introduce --enable-parport, add Solaris. + * lexer.l: replace str by strng to work around problems in some + versions of flex. + * main.c: move getexitspecs into the respective programmer's + domain; replace rindex by the C-standard strrchr. + * par.c: make parallel port optional. + * par.h: everything but par_initpgm() is private now. + * pgm.h: add setping/getping/highpulsepin/getexitspecs. + * serbb_posix.c: generalize bitbang interface; replace + cfmakeraw() by explicit code. + * serbb_win32.c: generalize bitbang interface. + +2005-10-20 Joerg Wunsch + + * butterfly.c: fix yet another sign extension bug. + +2005-10-14 Joerg Wunsch + + * avrdude.conf.in (ATmega8515): fix size of calibration + memory. + +2005-10-09 Joerg Wunsch + + * avrdude.conf.in: add support for ATmega640/1280/1281. + * avrdude.1: document the above. + * doc/avrdude.texi: (Ditto.) + +2005-09-27 Joerg Wunsch + + * doc/avrdude.texi: Polish up the docs a bit. Use smallexample + instead of example for wide tty output. Document a trick to + find out about the serial numbers of all JTAG ICEs attached + to USB. + +2005-09-26 Joerg Wunsch + + * jtagmkII.c (jtagmkII_paged_write): default the page size early so the + buffer will be allocated correctly. + * usb_libusb.c: fix libusb handling; now it works with libusb-win32 as + well. + +2005-09-21 Joerg Wunsch + + * main.c(do_op): use mem->desc in place of upd->memtype to + give the full name of the respective memory area, instead of + the (possibly abbreviated) name the user typed in the -U option. + +2005-09-21 Joerg Wunsch + + * main.c: Add the forgotten -B option to the option string in + getopt(); sort the -s option into order. + +2005/09/21 Brian S. Dean + + * avr.c: + * main.c: + * safemode.c: + * safemode.h: + * term.h: + This is Colin O'Flynn's mega patch for updating safemode support: + + * add support for parts with just 'fuse' memory + + * if any fuse memories are altered, reflect those changes in the + post-programming safemode check so that safemode no longer + complains about fuses which were intentionally altered; this + eliminates the need to completely disable safemode using -u in + order to program fuses. + + * provide -s option which will not ask to restore fuses, it will + just do it + +2005-09-19 Joerg Wunsch + + * butterfly.c (butterfly_initialize): make the device code unsigned so + it wouldn't sign-extend when >= 0x80. + +2005-09-18 Joerg Wunsch + + Add the serial bit-bang driver, contributed by Michael Holzt. + * bitbang.h: New file. + * bitbang.c: New file. + * serbb.h: New file. + * serbb_posix.c: New file. + * serbb_win32.c: New file. + * Makefile.am: Include new files. + * config_gram.y: Add serbb to configuration language. + * lexer.l: (Ditto.) + * par.c: Centralize bit-bang code in bitbang.c. + * par.h: Declare newly published functions. + * pgm.h (struct programmer_t): Add a flag field for private use + by the programmer. + * pindefs.h: Add definitions for negated serbb pins. + * avrdude.conf.in: Add serbb programmers ponyser, dasa, and dasa3. + * avrdude.1: Document serbb code. + * doc/avrdude.texi: (Ditto.) + +2005/09/18 Brian S. Dean + + * avrdude.conf.in: Patch #4078: add VCC pin definition for DAPA + programmer. + +2005/09/18 Brian S. Dean + + * avr910.c: This is patch #3277 which appears to fix a number of + issues with the avr910 programmer. + + Fixes the following problems with paged writes in avr910.c: + - failure to re-set address after page writes; + - no polling or delay after page writes; + - no page writes when not using auto-increment; + - an extraneous page write when data ends on page boundary. + +2005-09-17 Joerg Wunsch + + * avrdude.conf.in: Fix the poll values for the ATmega103's EEPROM + so they eventually match the XML file. + This fixes bug #7492: EEPROM writing fail on atmega103 with + atavrisp + +2005-09-17 Joerg Wunsch + + * avrdude.conf.in: The ATmega128 has four oscillator calibration + bytes, not only a single one. + This closes bug #11496: Memory bank calibration on atmega128 + should have 4 bytes + +2005/09/17 Brian S. Dean + + * avrdude.1: + Document -q -q. Expand a little on the description of the 'part' + command. + +2005/09/16 Brian S. Dean + + * fileio.c: + * main.c: + Implement -q -q to be very very quiet. + +2005/09/16 Brian S. Dean + + * avrdude.conf.in: + Add DAPA programmer. + +2005/09/16 Brian S. Dean + + * avrdude.conf.in: + * stk500v2.c: + This fixes EEPROM access using the STK500V2 programmer, partially + undoing part of a previous general fixup commit. Choose the correct + read/write operations with the stk500v2 program function - the correct + one depends on the memory type. EEPROM is byte addressable so uses + read/write. FLASH is word addressable and so uses read_lo/write_lo. + +2005-09-16 Joerg Wunsch + + * avrdude.1: document the memtypes for -U + * doc/avrdude.texi: (Ditto.) + Closes bug #13501: should be listed in the man page + +2005-09-16 Joerg Wunsch + + * doc/Makefile.am: add logic to detect the misf^H^H^H^H + gratitous API change in recent versions of texi2html where + the output directory has changed names. + Fix for: + bug #13026: The build fails with texi2html 1.76 + bug #12715: make issues during install + patch #3091: commandline fix for latest version of texi2html + +2005-09-16 Joerg Wunsch + + * usb_libusb.c (usbdev_drain): actually implement draining to aid + synchronizing against a JTAG ICE in weird state. + +2005-09-16 Joerg Wunsch + + * butterfly.c: improve the butterfly initialization so it is more likely + to synchonize; [bug #9787: avrdude 4.4.0 correct butterfly interface] + +2005-09-14 Joerg Wunsch + + * jtagmkII.c (jtagmkII_paged_load): return the number of bytes read. + This makes EEPROM block reads work again. + +2005-09-14 Joerg Wunsch + + * avrdude.conf.in: add a jtag2slow programmer alias, and make + "jtag2" default to 115200 Bd. + * doc/avrdude.texi: document the above changes. + +2005/09/14 Brian S. Dean + + * avrdude.conf.in: + Change bit 0 of the ATmega169 efuse 'write' opcode from 'x' (ignore) + to 'i' (input). Even though this bit should be ignored, it should not + be changed. The 'x' setting sets the bit to zero which programs it + and could cause undefined behaviour. Setting to 'i' enables it to be + rewritten to its old value. + + A better solution might be to read the fuse byte, apply the new value + while leaving the 'x' bit alone, then writing the value back. The + current fix is a workaround which allows the developer to change the + bit as desired. + +2005-08-30 Joerg Wunsch + + * usb_libusb.c: Consistently use unsigned char for buffers. + +2005-08-29 Brian S. Dean + + * avr910.c: Eliminate compiler warnings. GCC 4.x elicits many + signedness warnings when passing unsigned char * when char * is in + the prototype and vice versa. Clean these up along with a few + others. + * butterfly.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * safemode.c: (Ditto.) + * safemode.h: (Ditto.) + * ser_posix.c: (Ditto.) + * serial.h: (Ditto.) + * stk500.c: (Ditto.) + * stk500v2.c: (Ditto.) + +2005-08-28 Joerg Wunsch + + * avrdude.conf.in: Add support for the ATtiny25/45/85. Note that + only the ATtiny45 appears to have a complete XML description right + now. + * avrdude.1: Mention all the recently added device support: AT90PWM2/3, + ATmega164/324/644, ATmega329x/649x, ATtiny25/45/85. + * doc/avrdude.texi: (Ditto.) + +2005/08/28 Brian S. Dean + + * avrdude.conf.in: + * stk500v2.c: + This is patch # 4338, obsoletes patch #4327, provides fixes for bugs + #13693, #13871, and #14212. + + This provides bug fixes to the STK500V2 programmer type. + + - incorrect token used from avrdude.conf.in + - wrong command sent to programmer, hence no write to eeprom. + - programmer was said to start writing at 0x0000 and continue + page by page and was not repositionned when a gap was found + in the hex file, or when the hex file start address was not + 0x0000. Hence the verify procedure was correct, not the + write procedure. + - speed up of flash write to skip empty pages (full of 0xFF) + by re-enabling a dedicated function for that task. + - stk500v2_paged_load() was not returning the number of byte + read, so empty hex files were generated when reading memory. + +2005-08-17 Joerg Wunsch + + * avrdude.conf.in: fix the EEPROM size for ATmega329x/649x. + +2005-08-16 Joerg Wunsch + + * avrdude.conf.in: Add support for the AT90PWM2/3. + +2005-07-27 Joerg Wunsch + + (This work has been done as part of a contract with Atmel, Dresden.) + * butterfly.c: Implement full support for AVR109 boot loaders. + * avrdude.conf.in: add avr109 and avr911 as alias for butterfly. + * avrdude.1: Document the AVR109 addition. + * doc/avrdude.texi: (Ditto.) + +2005-07-26 Brian S. Dean + + * main.c: + Don't call exit() directly here - set the exit value and jump to the + main_exit: label to ensure the programmer is released correctly. + + * stk500v2.c: + The stk500v2_getsync() function was improperly checking for success, + thus it was falsely reporting that it failed when it was actually + working correctly. Fixed. + +2005-07-25 Joerg Wunsch + + * usb_libusb.c: Catch benign errors when reading the serial #. + +2005-06-19 Joerg Wunsch + + * Makefile.am: Implement libusb-base USB transport for the + JTAG ICE mkII. + * configure.ac: ditto. + * jtagmkII.c: ditto. + * ser_posix.c: ditto. + * ser_win32.c: ditto. + * serial.h: ditto. + * usb_libusb.c: ditto (New file). + * avrdude.1: document the USB transport. + * doc/avrdude.texi: ditto. + +2005-06-15 Joerg Wunsch + + * avrdude.conf.in: The AT90CAN128 has AllowFullPageBitstream = no. + +2005-06-14 Joerg Wunsch + + * avrdude.conf.in: Add support for the ATmega164/324/644. + * jtagmkII.c: If enter_progmode fails with RSP_ILLEGAL_JTAG_ID, give + the user a hint that the JTAGEN fuse might be unset. + +2005-06-11 Joerg Wunsch + + * avrdude.conf.in: Add support for the ATmega329x/649x. + +2005-05-27 Joerg Wunsch + + * jtagmkII.c: fix a signedness bug when shifting bits; when + discarding a packet for being overly long, restart the state + machine instead of attempting to drop a preposterous amount + of data. + +2005-05-19 Joerg Wunsch + + * avrdude.1: + * doc/avrdude.texi: Document that the JTAG ICE mkII code currently + cannot write to flash one byte at a time. Also mention the bug + tracker interface on savannah. + +2005/05/14 Brian S. Dean + + * configure.ac: + * main.c: + Update version for beta release and copyright message. + Change the default port to 'serial' for the newly added serial + programmers stk500v2 and jtagmkii. + +2005-05-10 Joerg Wunsch + + * Makefile.am: + * avr910.c: + * avrdude.1: + * avrdude.conf.in: + * avrpart.c: + * avrpart.h: + * butterfly.c: + * config_gram.y: + * crc16.c: + * crc16.h: + * jtagmkII.c: + * jtagmkII.h: + * jtagmkII_private.h: + * lexer.l: + * main.c: + * pgm.h: + * serial.h: + * ser_posix.c: + * ser_win32.c: + * stk500.c: + * stk500v2.c: + * stk500v2.h: + * stk500v2_private.h: + * doc/avrdude.texi: + + Mega-commit to bring in both, the STK500v2 support from Erik + Walthinsen, as well as JTAG ICE mkII support (by me). + + Note that for the JTAG ICE, I did change a few things in the + internal API. Notably I made the serial receive timeout + configurable by the backends via an exported variable (done in + both the Posix and the Win32 implementation), and I made the + serial_recv() function return a -1 instead of bailing out with + exit(1) upon encountering a receive timeout (currently only done + in the Posix implementation). Both measures together allow me to + receive a datastreem from the ICE at 115 kbps on a somewhat lossy + PCI multi-UART card that occasionally drops a character. The JTAG + ICE mkII protocol has enough of safety layers to allow recovering + from these events, but the previous code wasn't prepared for any + kind of recovery. The Win32 change for this still has to be done. + +2005/02/11 Brian S. Dean + + * main.c: + Exit non-zero if safe-mode reverts fuse bits that were requested on + the command-line. + + Variable declarations must only appear at the beginning of a block. + +2005/02/10 Brian S. Dean + + * avrdude.1: + Document -u option to disable safe mode. + +2005/02/10 Brian S. Dean + + * configure.ac: + doc/Makefile is now dependent on whether or not doc is enabled. + +2005/02/10 Brian S. Dean + + * Makefile.am: + * configure.ac: + Disable the doc build by default; the tools needed to build + doc are either not available on all systems or are at best + inconvenient to build and install. The doc can still be built, one + just needs to specify --enable-doc at configure time. + +2005-01-24 Colin O'Flynn + + * main.c: Add "safe mode". Fuse settings will be restored at the end + of a programming session unless the -u switch is specified. + * safemode.c: New file. Safe mode support. + * safemode.h: New file. Safe mode support. + * Makefile.am: Add new files. + * doc/avrdude.texi: Document new Safe Mode feature and switch. + +2004/12/22 Brian S. Dean + + * avrdude.conf.in: + Add support for "Xilinx JTAG cable". Contributed by: + Tymm + + Add support for the AT90CAN128. Not sure if all the instruction + encoding is correct, specifically the address bits don't exactly match + those of the preliminary datasheet that I have, but I don't see how + they could be right. Tested with STK500 and it works there. + Instruction encodings have not been tested due to lack of a parallel + port on my Mac development box. + +2004-07-19 Theodore A. Roth + + * avrdude.1: Remove reference to ppi programmer schematic. + * configure.ac (AC_INIT): Set version to "4.4.0cvs". + +2004-07-18 Theodore A. Roth + + * AVRDUDE 4.4.0 has been released (cvs release tag is "release_4_4_0"). + +2004-07-18 Theodore A. Roth + + * Makefile.am (EXTRA_DIST): Remove avrdude.pdf since it is no longer + supplied. + * NEWS: Fix typo. + * bootstrap: Delete the autom4te.cache dir before running the + autotools. + * configure.ac (AC_INIT): Set version to 4.4.0. + +2004-07-17 Jan-Hinnerk Reichert + + * avrdude.1: Fixed obvious copy and paste error + (Patch #3199 contributed by Galen Seitz) + +2004-07-15 Theodore A. Roth + + * main.c (main): Don't indent CPP directives. + When showing update progress in a no tty situation, use unbuffered IO + for all systems, not just win32 native. + Update copyright year when printing version. + Remove warning about native win32 being experimental. + Split a line string. + * ppiwin.c: Update copyright year. + Add cvs Id keyword. + (usleep): Cleanup debug CPP directives to improve readability. + * ser_win32.c: Include to fix failing build. + +2004-07-08 Theodore A. Roth + + * AUTHORS: Add names of recent major contributors. + * ser_win32.c: Assign copyright to Martin J. Thomas since he did all + real work on this file. + +2004-07-07 Jan-Hinnerk Reichert + + * NEWS, doc/TODO: Updated NEWS and TODO + +2004-07-07 Jan-Hinnerk Reichert + + * stk500.c, term.c, doc/avrdude.texi, avrdude.1: + added "sck"-command to the terminal mode. + This command allows slowing down of the SCK of + STK500-programmers. + +2004-07-05 Jan-Hinnerk Reichert + + * *.c, *.h: Removed unnecessary includes of + config.h + +2004-07-04 Jan-Hinnerk Reichert + + * avr.h: Removed some unused prototypes + +2004-07-04 Jan-Hinnerk Reichert + + * stk500.c: Fixed fosc behaviour for values exceeding + maximum frequency (contributed by Galen Seitz) + +2004-07-04 Jan-Hinnerk Reichert + * avrdude.conf.in: Added support for + ATtiny2313 (contributed by Bob Paddock) + +2004-06-25 Joerg Wunsch + + * avrdude.conf.in: Fix efuse bits for ATmega169. + +2004-06-24 Alex Shepherd + + Merged in Win32 Native changes contributed by Martin Thomas + Changed all instances of __CYGWIN__ conditional compilation to + WIN32NATIVE + + * ser_win32.c: fleshed out all the previous stubs + * ser_posix.c: added WIN32NATIVE conditional compilation to skip + all function to allow ser_win32.c functions to operate + * ppi.h: removed commented code + * pgh.h: added usleep macros + * main.c: stdout,stderr tweaks for Win32 + * configure.ac: added CFLAGS and LDFLAGS for Win32Native + * config_gram.y: added strtok_r macro + * buterfly.c: added various stub functions and EXIT processing + * avr910.c: added return 0 to avr910_open() and included time headers + * term.c: added warning about libreadline not supported in WIN32NATIVE + +2004-06-17 Jan-Hinnerk Reichert + + * avrdude.conf.in: Added support for + - tiny13 (contributed by Pawel Moll) + - mega48 and mega88 (contributed by Galen Seitz) + However, the STK500-code for mega8 remains unchanged. + +2004-05-19 Brian S. Dean + + * main.c: + * stk500.c: Allow the baud rate to be specified on the command + line with a new -b switch. The specified baud rate will + override the default serial port baud rate for a particular + programmer. + +2004-05-19 Brian S. Dean + + * ppi.c: Stub-out the ppi_* functions in ppi.c with empty + wrappers that simply return an error code in order to build + successfully on MacOS X. This allows avrdude to work on MacOS + X and was tested using a USB<->RS232 cable adapter, + specifically Keyspan model USA-19HS. + +2004-04-23 Joerg Wunsch + + * lists.h, lists.c: Drop LISTSZ and the check for + it in lcreat(). + +2004-04-17 Jan-Hinnerk Reichert + + * avr910.c: Hopefully fixed that weird "first byte not + programmed"-error in a good way (previous fix was not + working with all firmwares) + +2004-02-10 Jan-Hinnerk Reichert + + * avrdude.1, doc/avrdude.texi, doc/TODO: + Removed the deprecated options from documentation + +2004-02-10 Jan-Hinnerk Reichert + + * main.c: Removed deprecated options. + +2004-01-28 Jan-Hinnerk Reichert + + * pgm.c, main.c, avr910.c, butterfly.c, stk500.c: + Changed default for powerup, powerdown and LED-commands + to do nothing and return OK. Then removed these commands + from avr910, butterfly and stk500. + * pgm.c: Fixed wrong type for default_open introduced by + the cleanup yesterday. + +2004-01-29 Jan-Hinnerk Reichert + + * par.c: changed order of port-read/writes in par_txrx(). + This change should increase immunity to delays in the + programmer-hardware. + Also did some unrelated cleanup in par_txrx(). + +2004-01-28 Jan-Hinnerk Reichert + + * pgm.[ch], main.c, par.c, avr910.c, butterfly.c, stk500.c: + Move save/restore-functionality into open/close. + * par.c: open/close now saves/restores PPICTRL, too. + * TODO: exitspecs don't work if RESET is in PPICTRL. + +2004-01-26 Theodore A. Roth + + * configure.ac (AC_INIT): Post release version update. + +2004-01-26 Theodore A. Roth + + * AVRDUDE 4.3.0 has been released (cvs release tag is "release_4_3_0"). + +2004-01-26 Theodore A. Roth + + * configure.ac: Update copyright year. + (AC_INIT): Set version to 4.3.0. + +2004-01-25 Theodore A. Roth + + * ChangeLog: Minor formatting cleanups. + Move to all 2003 entries to ChangeLog-2003. + * ChangeLog-2003: New file. + * Makefile.am: Update copyright year. + (EXTRA_DIST): Add ChangeLog-2003. + +2004-01-17 Jan-Hinnerk Reichert + + * doc/avrdude.texi: Get rid of those black boxes marking "overfull + hbox". + +2004-01-17 Jan-Hinnerk Reichert + + * doc/avrdude.texi: New appendix "Troubleshooting". + +2004-01-12 Jan-Hinnerk Reichert + + * avr910.c, avrpart.c, avrpart.h, doc/TODO: + Look up devicecode and report device. + +2004-01-03 Jan-Hinnerk Reichert + + * avr910.c, pgm.c, pgm.h, config_gram.y, lexer.l: Add new configuration + parameter baudrate to support avr910-programmers with non-standard + baudrates. + * avrdude.conf.in, doc/avrdude.texi: Added "baudrate" to documentation. + +2004-01-03 Jan-Hinnerk Reichert + + * avr910.c: Removed debugging stuff that is no longer needed. + +2004-01-03 Jan-Hinnerk Reichert + + * doc/TODO: Removed two items. + +2004-01-03 Jan-Hinnerk Reichert + + * main.c, avr.c, avr.h, par.c, stk500.c: Add function + avr_chip_erase() to unify handling of cycle-count. + Makes cycle-count work for avr910-programmers. + diff --git a/avrdude/ChangeLog-2007 b/avrdude/ChangeLog-2007 new file mode 100644 index 00000000..3514da7e --- /dev/null +++ b/avrdude/ChangeLog-2007 @@ -0,0 +1,364 @@ +2007-11-08 Joerg Wunsch + + * main.c: Partially revert the line buffered output change, + and turn stderr into unbuffered output while producing the + progress report. + +2007-11-07 Joerg Wunsch + + * main.c: Add setup and teardown hooks to the programmer + definition. If present, call the setup hook immediately after + finding the respective programmer object, and schedule the + teardown hook to be called upon exit. This allows the + programmer implementation to dynamically allocate private + programmer data. + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * avr910.c: Convert static programmer data into dynamically + allocated data. + * butterfly.c: (Ditto.) + * jtagmkI.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * stk500v2.c: (Ditto.) + * usbasp.c: (Ditto.) + * usbtiny.c: (Ditto.) + +2007-11-06 Joerg Wunsch + + * butterfly.c: Remove the no_show_func_info() calls, as Brian + promised some 4 years ago. + +2007-11-06 Joerg Wunsch + + * main.c: Add the -x option to pass extended parameters to + the programmer backend. + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * jtagmkII.c: Implement the extended parameter jtagchain= + to support JTAG daisy-chains. + * avrdude.1: Document all of the above. + * doc/avrdude.texi: (Ditto.) + +2007-10-30 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version for post-release. + +2007-10-29 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version, releasing avrdude-5.5. + +2007-10-29 Joerg Wunsch + + Submitted by : + patch #5007: Patch for line-buffering of stdout and stderr + * main.c: call setvbuf() for stdout and stderr. + +2007-10-29 Joerg Wunsch + + Submitted by : + patch #5953: Add AT90CAN64 and AT90CAN32 to avrdude.conf + * avrdude.conf.in: Add entry for AT90CAN64 and AT90CAN32. + +2007-10-29 Joerg Wunsch + + Submitted by Wolfgang Moser: + patch #6121: ISP support for the C2N232I device (serial port + bitbanging) + * avrdude.conf.in: Add entry for c2n232i. + +2007-10-29 Joerg Wunsch + + Submitted by : + patch #6141: accept binary format immediate values + * fileio.c: Detect a 0b prefix, and call strtoul() differently + in that case. + +2007-10-29 Joerg Wunsch + + bug #21076: -vvvv serial receive prints are empty in Win32 build + * ser_win32.c (ser_recv): Drop the essentially unused variable + "len", and use the variable "read" in order to track how many + bytes have just been read in. + +2007-10-29 Joerg Wunsch + + bug #21145: atmega329p not recognized + * avrdude.conf.in: Add definitions for the ATmega329P/3290P. + Same as ATmega329/3290 except of the different signature. + +2007-10-29 Joerg Wunsch + + bug #21152: Unable to program atmega324p with avrdude 5.4 and AVRISP + using default configuration file. + * avrdude.conf.in: Uncomment the (bogus) stk500_devcode lines for + the ATmega164P, ATmega324P, ATmega644, and ATmega644P definitions. + This only affects users of STK500v1 firmware. + +2007-10-29 Joerg Wunsch + + Submitted by : + Patch #6233: Add support for USBtinyISP programmer + * usbtiny.c: New file. + * usbtiny.h: (Ditto.) + * Makefile.am: Include usbtiny into the build. + * avrdude.conf.in: (Ditto.) + * config_gram.y: (Ditto.) + * lexer.l: (Ditto.) + * avrdude.1: Document the usbtiny support. + * doc/avrdude.texi: (Ditto.) + +2007-10-29 Joerg Wunsch + + * doc/avrdude.texi: Sort list of supported programmers into + alphabetical order, add all missing programmers. + +2007-07-24 Thomas Fischl + + * usbasp.c: Added long addresses to support devices with more + than 64kB flash. Closes bug #20558: Long address problem with + USBasp. + +2007-06-27 Joerg Wunsch + + * Makefile.am (EXTRA_DIST): Add ChangeLog-2004-2006. + +2007-05-16 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version for post-release. + +2007-05-16 Joerg Wunsch + + * configure.ac (AC_INIT): Bump version, releasing avrdude-5.4. + +2007-05-16 Joerg Wunsch + + * avrdude.conf.in: Fix AVR910 devcodes. It seems that the AVR109 + listing refers to "BOOT"-type code, while the standard codes are + different (usually one below). + +2007-05-16 Joerg Wunsch + + * avr.c (avr_read, avr_write): only use the paged_load and + paged_write backend functions iff the memory area in question has + a page_size != 0. + This is supposed to fix bug #19234: avrdude-5.3.1 segfaults when + stk500v1 tries to program an ATtiny15 + +2007-05-15 Joerg Wunsch + + * avr910.c: Fall back to avr_{read,write}_byte_default(). Fixes + bug #18803: Fuse reading regression in avrdude 5.3.1 with avr910 + programmer + +2007-05-15 Colin O'Flynn + + * avrdude.conf.in: Rename the ATmega164 and ATmega324 into + ATmega164P and ATmega324P, resp. Add an entry for the ATmega644P. + Fixes bug #19769: ATmega164p not recognized + +2007-05-15 Joerg Wunsch + + * ser_posix.c (ser_send): Don't select() on the output fd before + trying to write something to the serial line. That kind of + polling isn't very useful anyway, and it seems it breaks for the + Linux CP210x USB<->RS-232 bridge driver which is certainly a bug + in the driver, but we can just avoid that bug alltogether. + +2007-05-15 Joerg Wunsch + + * avrdude.conf.in: Fix the STK500v2 ISP delay parameter for + ATmega640/1280/1281/2560/2561. Atmel has changed the XML + files after the initial release. + +2007-05-01 Colin O'Flynn + + * safemode.c: -Oops - bug in verbose output. Fixed. + -Fixed handling of cases where programmer cannot read fuses (AVR910) + * main.c: -Also fixing handling of cases where programmer cannot + read fuses + This should close one or more bugs (18803, 19570) + +2007-05-01 Colin O'Flynn + + * safemode.c: Added verbose output from safemode routines. + +2007-03-25 Colin O'Flynn + + * stk500generic.c: Forgot to close the serial port before trying to + open it again, caused problems on Windows machines. + Closes bug #19411 + +2007-02-26 Joerg Wunsch + + * avrdude.conf.in: Add the AT90PWM2/3B devices. + +2007-02-02 Thomas Fischl + + * usbasp.c: Changed return value of function usbasp_initialize to stop + avrdude on communication errors between programmer and target. + Closes bug #18581: safemode destroys fuse bits + +2007-02-01 Joerg Wunsch + + * config_gram.y: Remove duplicate definition of token K_WRITEPAGE + +2007-01-30 Joerg Wunsch + + * butterfly.c: Implement ATmega256x support for butterfly/avr109. + +2007-01-30 Joerg Wunsch + + * configure.ac: Fix subdir handling. Now finally, "make + distcheck" will include the documentation into the tarball even if + the configure had been run without the --enable-doc. + +2007-01-30 Joerg Wunsch + + * safemode.c: Obtain progname from avrdude.h rather than trying to + roll our own (duplicate) copy of it. + * avr910.c: Constify char pointers. + * avrpart.c: (Ditto.) + * avrpart.h: (Ditto.) + * butterfly.c: (Ditto.) + * config.c: (Ditto.) + * config.h: (Ditto.) + * jtagmkI.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * par.c: (Ditto.) + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * serbb_posix.c: (Ditto.) + * serbb_win32.c: (Ditto.) + * stk500.c: (Ditto.) + * stk500v2.c: (Ditto.) + * usbasp.c: (Ditto.) + +2007-01-29 Joerg Wunsch + + * avrpart.c: More backend/library abstraction and generalization: + turn the list_parts() and list_programmers() functions into + general list iteration functions that call a caller-supplied + callback for each element. Implement list_parts() and + list_programmers() as private functions in main.c based on that + approach. + * avrpart.h: (Ditto.) + * main.c: (Ditto.) + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + +2007-01-25 Joerg Wunsch + + * Makefile.am: Rearrange everything so it is now built into a + libavrdude.a library, and link main.c against that library. + * configure.ac: Add AC_PROG_RANLIB as we are building a library + now. + +2007-01-24 Joerg Wunsch + + Major code cleanup. + - Make all internal functions "static". + - Make sure each module's header and implementation file match. + - Remove all library-like functionality from main.c, so only + the actual frontend remains in main.c. + - Add C++ brackets to all header files. + * avr.c: (Ditto.) + * avr.h: (Ditto.) + * avr910.c: (Ditto.) + * avr910.h: (Ditto.) + * avrdude.h: (Ditto.) + * avrpart.c: (Ditto.) + * avrpart.h: (Ditto.) + * bitbang.h: (Ditto.) + * butterfly.h: (Ditto.) + * config.c: (Ditto.) + * config.h: (Ditto.) + * confwin.h: (Ditto.) + * crc16.c: (Ditto.) + * crc16.h: (Ditto.) + * fileio.c: (Ditto.) + * fileio.h: (Ditto.) + * jtagmkI.h: (Ditto.) + * jtagmkII.h: (Ditto.) + * lexer.l: (Ditto.) + * lists.h: (Ditto.) + * main.c: (Ditto.) + * par.h: (Ditto.) + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * ppi.c: (Ditto.) + * ppi.h: (Ditto.) + * safemode.h: (Ditto.) + * serbb.h: (Ditto.) + * serial.h: (Ditto.) + * stk500.h: (Ditto.) + * stk500v2.c: (Ditto.) + * stk500v2.h: (Ditto.) + * term.c: (Ditto.) + * term.h: (Ditto.) + * usbasp.h: (Ditto.) + * update.c: New file. + * update.h: New file. + * Makefile.am: Include update.c and update.h. + +2007-01-24 Joerg Wunsch + + Move all "extern" declarations into a centreal header file. + * Makefile.am: Add new avrdude.h. + * avrdude.h: New file. + * avr.c: Replace private extern decl's by #include "avrdude.h". + * avr910.c: (Ditto.) + * avrpart.c: (Ditto.) + * bitbang.c: (Ditto.) + * butterfly.c: (Ditto.) + * config.c: (Ditto.) + * config_gram.y: (Ditto.) + * fileio.c: (Ditto.) + * jtagmkI.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * lexer.l: (Ditto.) + * main.c: (Ditto.) + * par.c: (Ditto.) + * pgm.c: (Ditto.) + * ppi.c: (Ditto.) + * ppiwin.c: (Ditto.) + * ser_avrdoper.c: (Ditto.) + * ser_posix.c: (Ditto.) + * ser_win32.c: (Ditto.) + * serbb_posix.c: (Ditto.) + * serbb_win32.c: (Ditto.) + * stk500.c: (Ditto.) + * stk500generic.c: (Ditto.) + * stk500v2.c: (Ditto.) + * term.c: (Ditto.) + * usb_libusb.c: (Ditto.) + * usbasp.c: (Ditto.) + +2007-01-13 Joerg Wunsch + + * avrdude.conf.in (ATmega8): Bump the delay values for flash + and EEPROM, based on the current Atmel XML file. + +2007-01-12 Joerg Wunsch + + * configure.ac: Improve the detection of the Win32 HID library, + and the presence of the header ddk/hidsdi.h. It now works + correctly under Cygwin and several flavours of MinGW. + * Makefile.am: Add new LIBHID pattern. + +2007-01-11 Joerg Wunsch + + * butterfly.c (butterfly_initialize): when sending the 'T' + command (which is ignored by current AVR109 bootloaders), + send the first reply from the list of supported device + codes back rather than using avrdude.conf's idea about + an AVR910 device code. Apparently, this solves disagreements + between different versions of at least the ATmega8 AVR910 + device code. + Closes bug #18727: Writing flash failed + +2007-01-07 Joerg Wunsch + + Reported by Till Harbaum: + * avrdude.conf.in (ATtiny25/45/85): Change HVSP reset from + 500 microseconds to 1 ms, matching the most recent Atmel XML + specs. diff --git a/avrdude/ChangeLog-2008 b/avrdude/ChangeLog-2008 new file mode 100644 index 00000000..f43a10ab --- /dev/null +++ b/avrdude/ChangeLog-2008 @@ -0,0 +1,185 @@ +2008-11-20 Joerg Wunsch + + * avrdude.h: Change the prototype for usleep() to be more Cygwin- + friendly. + * ppiwin.c: (Ditto.) + +2008-11-06 Joerg Wunsch + + Submitted by limor + * usbtiny.c (usbtiny_cmd): Replace sizeof() by a fixed constant + 4 for the result array, because otherwise it would take the size + of a pointer which miserably fails on 64-bit machines. + +2008-11-05 Joerg Wunsch + + patch #6609: Using PCI parallel port cards on Windows + * ppiwin.c (ppi_open): If the port parameter passed from the + -p option is neither lpt1/2/3, try interpreting it directly as + a base address. + * avrdude.1: Document the change. + * doc/avrdude.texi: (Ditto.) + +2008-11-04 Joerg Wunsch + + bug #22882: Erase Cycle Counter does not work for stk500v2 + * stk500v2.c (stk500v2_chip_erase,stk500hv_chip_erase): Return + the expected 0 for success rather than a protocol-dependant + number. + +2008-11-04 Joerg Wunsch + + bug #22883: Chip Erase performed even with no-write flag (-n) + * main.c: Do not erase the chip if both, -e and -n options have + been specified. + +2008-11-04 Joerg Wunsch + + bug #24589: AT90USB64* have wrong signature + * avrdude.conf.in: Uncomment the correct, and delete the wrong + signature for AT90USB646/647. Alas, the datasheet has never been + corrected for years. + +2008-10-31 Joerg Wunsch + + * jtagmkII.c: Fix a serious memory corruption that happened when + using the JTAG ICE mkII (or AVR Dragon) in ISP mode. The wrong + set of per-programmer private data had been allocated (stk500v2 + vs. jtagmkII) which was too small to hold the actual data. + * jtagmkII.h: (Ditto.) + * stk500v2.c: (Ditto.) + +2008-07-29 Joerg Wunsch + + * jtagmkII.c: Implement Xmega JTAG support. + * jtagmkII_private.h: Add EMULATOR_MODE_JTAG_XMEGA. + +2008-07-29 Joerg Wunsch + + * main.c: Remember whether the device initialization worked, and + allow to continue with -F if it failed yet do not attempt to + perform anything on the device itself. That way, -tF could be + specified for programmers like the STK500/STK600 even without a + device connected, just in order to allow changing parameters on + the programmer itself. + * avrdude.1: Document that possible use of the -F option. + * doc/avrdude.texi: (Ditto.) + +2008-07-29 Joerg Wunsch + + * stk500v2.c (stk600_xprog_paged_write): Fix a fatal miscalculation + of the number of bytes to be written which caused a malloc chunk + corruption. + +2008-07-27 Joerg Wunsch + + First implementation of ATxmega support. By now, only the + PDI mode of the STK600 is supported. Single-byte EEPROM + (and flash) updates do not work yet. + * avr.c: "boot" memory is a candidate memory region for paged + operations, besides "flash" and "eeprom". + * avrdude.conf.in: add ATxmega128A1 and ATxmega128A1revD + * avrpart.h: add the AVRPART_HAS_PDI flag (used to distinguish + ATxmega parts from classic AVRs), the nvm_base part field, and + the offset field for a memory region. + * config_gram.y: add "has_pdi", "nvm_base", and "offset" + * lexer.l: (Ditto.) + * main.c: disable auto_erase for ATxmega parts + * stk500v2.c: implement the XPROG functionality, and divert to + this for ATxmega parts + * avrdude.1: Document the changes. + * doc/avrdude.texi: (Ditto.) + +2008-07-25 Joerg Wunsch + + Fix a bunch of warnings. + * avr910.c (avr910_paged_load): possible unitialized use of + rd_size + * jtagmkI.c (jtagmkI_initialize): pointer signedness mixup + * jtagmkII.c (jtagmkII_print_parms1): propagate const'ness + of parameter + * usbasp.c (usbasp_transmit): pointer signedness mixup + * ser_avrdoper.c (usbGetReport): remove useless pointer deref + +2008-07-25 Joerg Wunsch + + Contributed by Ville Voipio: + patch #6501: New autotools support for avrdude + * Makefile.am: add @WINDOWS_DIRS@ to SUBDIR + * bootstrap: allow for autconf-2.61 and automake-1.10, too + * configure.ac: fix @WINDOWS_DIRS@ recursion, replace + AC_PROG_CC by AM_PROG_CC_C_O, for esoteric reasons + +2008-06-13 Joerg Wunsch + + Contributed by Janos Sallai : + patch #6074: added support for crossbow's MIB510 programmer + * avrdude.conf.in: Add entry for mib510. + * stk500.c: Add special hooks to handle the MIB510 programmer. + It mostly talks STK500v1 protocol but has a special hello and + goodbye sequence, and uses a fixed block size of 256 bytes. + * doc/avrdude.texi: Document support for mib510. + +2008-06-07 Joerg Wunsch + + Contributed by Klaus Leidinger : + * main.c: Realign verbose messages. + * avrpart.c: (Ditto.) + * avr910.c: Print the device code selected in verbose mode. + * butterfly.c: (Ditto.) + +2008-06-07 Joerg Wunsch + + Contributed by Klaus Leidinger : + Add check for buffermode feature, and use it if present. Can be + turned off using -x no_blockmode. + * avr910.c: Implement buffermode test and usage. + * avrdude.1: Document -x no_blockmode. + * doc/avrdude.texi: (Ditto.) + +2008-03-24 Joerg Wunsch + + * usb_libusb.c: #undef interface for Win32 + +2008-03-24 Joerg Wunsch + + * avr910.c: Add support for the -x devcode option. + * avrdude.1: Document -x devcode for avr910. + * doc/avrdude.texi: (Ditto.) + +2008-03-14 Joerg Wunsch + + Add initial support for the Atmel STK600, for + "classic" AVRs (AT90, ATtiny, ATmega) in both, + ISP and high-voltage programming modes. + * Makefile.am: Add -lm. + * avrdude.conf.in: Add stk600, stk600pp, and stk600hvsp. + * config_gram.y: Add support for the stk600* keywords. + * lexer.l: (Ditto.) + * pgm.h: Add the "chan" parameter to set_varef(). + * stk500.c: (Ditto.) + * serial.h: Add USB endpoint support to struct filedescriptor. + * stk500v2.c: Implement the meat of the STK600 support. + * stk500v2.h: Add new prototypes for stk600*() programmers. + * stk500v2_private.h: Add new constants used in the STK600. + * term.c: Add AREF channel support. + * usb_libusb.c: Automatically determine the correct write + endpoint ID, the STK600 uses 0x83 while all other tools use + 0x82. Propagate the EP to use through struct filedescriptor. + * usbdevs.h: Add the STK600 USB product ID. + * tools/get-stk600-cards.xsl: XSL transformation for + targetboards.xml to obtain the list of socket and routing + card IDs, to be used in stk500v2.c (for displaying the + names). + * tools/get-stk600-devices.xsl: XSL transformation for + targetboards.xml to obtain the table of socket/routing cards + and their respective AVR device support for doc/avrdude.texi. + * avrdude.1: Document all the STK600 stuff. + * doc/avrdude.texi: Ditto. Added a new chapter for + Programmer Specific Information. + +2008-01-26 Joerg Wunsch + + * stk500v2.c (stk500v2_recv): Make length computation unsigned so + it cannot accidentally become negative. + diff --git a/avrdude/ChangeLog-2009 b/avrdude/ChangeLog-2009 new file mode 100644 index 00000000..1f993cbc --- /dev/null +++ b/avrdude/ChangeLog-2009 @@ -0,0 +1,411 @@ +2009-11-09 David Hoerl + + * fileio.c: ihex2bin did not properly handle files > 64K bytes + * usb_libusb.c: re-enabled usb_reset for Macs (no reset causes lots of failures) + * avrdude.1: spacing issue for avr32 fixed. + +2009-11-09 Michal Ludvig + + * buspirate.c: Implemented reset= and speed= extended parameters. + * avrdude.1: Document the change. + +2009-11-04 Michal Ludvig + + * configure.ac, Makefile.am: Test if GCC accepts -Wno-pointer-sign + +2009-11-04 Michal Ludvig + + * buspirate.c: Implemented 'BinMode' support for + firmware 2.7 and higher. + * avrdude.1: Added info about BusPirate. + +2009-11-03 Michal Ludvig + + * arduino.c: Add on to bug #26703 / patch #6866 - clear DTR/RTS + when closing the port. + * Makefile.am: Silent warnings about signedness - they're useless + and annoying, especially for 'char' vars. + +2009-10-22 David Hoerl + + * usb_libusb.c: disabled usb_reset for Macs (same as FreeBSD) + +2009-10-12 Michal Ludvig + + * main.c: Re-added default to serial port for BusPirate. + +2009-10-12 David Hoerl + + * main.c: removed some avr32 code that was pushed into jtagmkII.c + * jtagmkII.c: consolodated the avr32 reset code and avr32_chipreset + * avrpart.h: modified AVRPART flags for avr32 + * lexer.l: added is_avr32 flag - only way to get yacc code to set flag + * avrdude.conf.in: updated avr32 section to include "is_avr32" flag + +2009-10-12 David Hoerl + + * config_gram.y: Restored inadvertantly removed buspirate entry + * lexer.l: Restored inadvertantly removed buspirate entry + +2009-10-12 Michal Ludvig + + * buspirate.c: Replace GNU-only %as with %s in sscanf call. + * ser_win32.c(ser_set_dtr_rts): Fixed typo in parameter name. + * NEWS: Announce BusPirate. + +2009-10-11 David Hoerl + + Support for AVR32 + + * AUTHORS: added myself + * NEWS: announced AVR32 support + * main.c: AVR32 flag tests to avoid several code blocks + * fileio.c: mods to ihex read function to handle address offsets and + size of avr32 + * jtagmkI.c: added cast to printf call to remove warning + * arduino.c: added header file to bring in prototype for usleep() + * config_gram.y: added defines for avr32, new jtag_mkii variant for avr32 + * jtagmkII_private.h: new jtag_mkii message types defined (used by + avr32program) + * jtagmkII.h: extern jtagmkII_avr32_initpgm() addition + * jtagmkII.c: huge amount of code in support of avr32 + * avrpart.h: additional flags to AVRPART for avr32 + * usb_libusb.c: modified verbose test for USB read per-byte messages by + by one, so with verbose=3 you get just full messages, 4 gives you bytes + too + * lexer.l: additions for avr32 + +2009-10-10 Michal Ludvig + + Support for Arduino auto-reset: + * serial.h, ser_avrdoper.c, ser_posix.c, ser_win32.c: Added + serial_device.set_dtr_rts implementations. + * arduino.c, stk500.c, stk500.h: Call serial_set_dtr_rts() + to reset Arduino board before program upload. + Inspired by patch #6866, resolves bug #26703 + +2009-10-08 Michal Ludvig + + * buspirate.c: Optimised buspirate_cmd() - reading 1kB EEPROM now + takes only 14 sec instead of almost 2 mins with the original + implementation. + +2009-10-08 Michal Ludvig + + * buspirate.c, buspirate.h: Support for the BusPirate programmer + * config_gram.y, avrdude.conf.in, main.c, lexer.l, Makefile.am: + Glue for BusPirate. + +2009-08-17 Joerg Wunsch + + * usb_libusb.c (usbdev_close): Repair the logic around the + conditional compilation of usb_reset() introduced in r798. + +2009-07-11 Joerg Wunsch + + * configure.ac: We are post-5.8 now. + +2009-07-11 Joerg Wunsch + + * configure.ac: Prepare for releasing version 5.8 + +2009-07-11 Joerg Wunsch + + Submitted by Roger Wolff: + bug #26527: bug in unicode conversion + * ser_avrdoper.c (convertUniToAscii): when encountering a UTF-16 + character that cannot be converted to ASCII, increment the UTF-16 + pointer anyway when proceeding. + +2009-07-11 Joerg Wunsch + + * jtagmkI.c (jtagmkI_send): Replace %zd format by %u since not all + implementations do understand the C99 formatting options (sigh). + * jtagmkII.c (jtagmkII_send): (Ditto.) + * stk500v2.c (stk500v2_recv): (Ditto.) + +2009-07-11 Joerg Wunsch + + bug #26002: HVPP of EEPROM with AVR Dragon and ATmega8 Fails + * avrdude.conf.in (ATmega8): add page size for EEPROM. + +2009-07-07 Joerg Wunsch + + * stk500v2.c: Fix a serious memory corruption problem resulting + out of the chaining of both, the stk500v2 and the jtagmkII + programmers for some programming hardware (JTAG ICE mkII and AVR + Dragon running in ISP, HVSP or PP mode), where both programmers + have to maintain their private programmer data. + +2009-07-02 Joerg Wunsch + + * configure.ac: Post-release (is pre-release...) + +2009-07-02 Joerg Wunsch + + * configure.ac: Prepare for releasing version 5.7 + +2009-07-02 Joerg Wunsch + + * main.c: Add my name to the copyright output when being verbose. + +2009-07-02 Joerg Wunsch + + Contributed by Shaun Jackman + bug #21798: Fix both XSLT scripts + * tools/get-dw-params.xsl (format-hex): Add the parameter count. + * tools/get-hv-params.xsl (format_cstack): Ditto. + +2009-07-02 Joerg Wunsch + + bug #21922: ATmega163 still not working in version 5.5 + * avrdude.conf.in (atmega163): fill in stk500v2 parameters, correct + some flash programming parameters as well. + +2009-07-02 Joerg Wunsch + + bug #22206: avrdude: ser_setspeed(): tcsetattr() failed + * ser_posix.c (ser_setspeed): Don't pass TCSAFLUSH to tcsetattr() as + it apparently fails to work on Solaris. After reading the + documentation again, it seems TCSAFLUSH and TCSANOW are indeed + mutually exclusive. + +2009-07-02 Joerg Wunsch + + bug #22234: WINDOWS version: HOWTO: Specify Serial Ports Larger than COM9 + * ser_win32.c (ser_open): prepend \\.\ to any COM port name, so it is + safe to be used for COM ports above 9. + +2009-07-02 Joerg Wunsch + + bug #26408: Crash in stk500v2_open() + * stk500generic.c: Implement setup and teardown hooks, calling in turn + the respective hooks of the stk500v2 implementation. + +2009-07-02 Joerg Wunsch + + bug #26130: Avrdude doesn't display it's version. + * main.c (usage): add a version number display to the default usage + message. + +2009-07-01 Joerg Wunsch + + bug #26412: avrdude segfaults when called with a programmer that does not + support it + * main.c: do not call pgm->perform_osccal() unless it is != 0. + +2009-06-24 Joerg Wunsch + + Contributed by Zoltan Laday: + patch #6825: xmega problems with JTAGICEmkII + * jtagmkII.c: Many fixes for Xmega devices. + * jtagmkII_private.h: Add various new constants required for + Xmega devices. + * avrdude.conf.in: New devices: ATXMEGA64A1, ATXMEGA192A1, + ATXMEGA256A1, ATXMEGA64A3, ATXMEGA128A3, ATXMEGA192A3, + ATXMEGA256A3, ATXMEGA256A3B, ATXMEGA16A4, ATXMEGA32A4, + ATXMEGA64A4, ATXMEGA128A4 + * avr.c (avr_read, avr_write): Add more names for (Xmega) + memory areas that require paged operation. + +2009-06-24 Joerg Wunsch + + * stk500v2.c (stk600_xprog_write_byte): Handle writing fuse bytes. + +2009-04-28 Joerg Wunsch + + Submitted by Carl Hamilton: + * update.c (parse_op): correctly \0-terminate buf after filling + it, before it is potentially used as the source of a call to + strlen or strcpy. + +2009-04-14 Joerg Wunsch + + * doc/avrdude.texi: Merge the -P 0xXXX option description from + avrdude.1. + +2009-04-14 Joerg Wunsch + + * configure.ac: declare AM_PROG_CC_C_O to avoid the warning + "compiling `config_gram.c' with per-target flags + requires `AM_PROG_CC_C_O' in `configure.ac'" + +2009-03-22 Joerg Wunsch + + bug #25971: "error writing to " with multiple -U params. + * fileio.c: Do not close the input/output stream when working on an + stdio stream. + +2009-02-28 Thomas Fischl + + Based on patch #6484 commited by Jurgis Brigmanis: + * usbasp.c: added software control for ISP speed + * usbasp.h: (Ditto.) + +2009-02-28 Joerg Wunsch + + * avr910.c (avr910_read_byte_flash): Eliminate a static variable that + hasn't been in use for 5 years. + +2009-02-27 Joerg Wunsch + + * configure.ac: Post-release 5.6. + +2009-02-27 Joerg Wunsch + + * configure.ac: Prepare for releasing version 5.6. + +2009-02-27 Joerg Wunsch + + Submitted by Ed Okerson: + * jtagmkII.c (jtagmkII_read_byte): Fix signature reading of + Xmega. + +2009-02-26 Joerg Wunsch + + Submitted by Mikael Hermansson: + * avrdude.conf.in (ATxmega256A3): new device. + * stk500v2 (stk500v2_initialize): Enable the AVRISPmkII as a + PDI-capable device for ATxmega parts. + +2009-02-25 Joerg Wunsch + + Submitted by Lars Immisch: + patch #6750: Arduino support - new programmer-id + * arduino.c: New file, inherits stk500.c. + * arduino.h: New file. + * Makefile.am: Add arduino.c and arduino.h. + * config_gram.y: Add arduino keyword. + * lexer.l: (Ditto.) + * avrdude.conf.in: (Ditto.) + * avrdude.1: Document the new programmer type. + * doc/avrdude.texi: (Ditto.) + +2009-02-25 Joerg Wunsch + + * stk500v2.c: Turn all non-const static data into instance data. + +2009-02-25 Joerg Wunsch + + * Makefile.am: Move term.[ch] from the library into the CLI + application section, as it is not useful for anything else but + the CLI frontend. + +2009-02-25 Joerg Wunsch + + * avrdude.conf.in (ATmega1284P): new device. + +2009-02-23 Joerg Wunsch + + More fixes for Solaris, including fixes for the Sunpro compiler: + * avr.h: Remove stray semicolon. + * configure.ac: Add check for predefined types uint_t and ulong_t. + * confwin.c: Include "avrdude.h" on top to avoid empty translation + unit warning. + * ppwin.c: (Ditto.) + * ser_win32.c: (Ditto.) + * serbb_win32.c: (Ditto.) + * jtagmkII.c (jtagmkII_recv): remove unreachable "return". + * stk500.c (stk500_initialize): (Ditto.) + * par.c: Test for both, __sun__ and __sun to see whether we are + being compiled on Solaris. + * ppi.c: (Ditto.) + * stk500v2.c: Implement the DEBUG and DEBUGRECV macros in a way + that is compatible with the ISO C99 standard. + * usbtiny.c: Only typedef uint_t and ulong_t if they have not + been found already by the autoconf checks. + +2009-02-23 Joerg Wunsch + + bug #22204: Solaris10/11 Undefiniertes Symbol gethostbyname socket + connect + * configure.ac: Add checks for gethostent() and socket(). + While being here, remove some old cruft left from ancient days. + +2009-02-22 Joerg Wunsch + + * lexer.l: Bump the %p size so AT&T lex will continue to work. + +2009-02-19 Joerg Wunsch + + (Partially) submitted by John Voltz: + bug #20004: AVRDUDE update (-U) operations do not close files + * fileio.c (fmt_autodetect, fileio): fclose() files. + +2009-02-18 Joerg Wunsch + + * usbtiny.c: Replace all but one (very unlikely to trigger) exit(1) + by return -1. + +2009-02-18 Joerg Wunsch + + Submitted by Dick Streefland: + patch #6749: make reading from the USBtinyISP programmer more robust + * usbtiny.c: Add code to retry failed communication attempts. + +2009-02-17 Joerg Wunsch + + Submitted by Nick Hibma: + bug #22271: usb_reset in usb_libusb.c not necessary in FreeBSD 6.x + * usb_libusb.c (usbdev_close): Do not call usb_reset() on FreeBSD. + It is not necessary there. + +2009-02-17 Joerg Wunsch + + Submitted by Andrew O. Shadoura: + bug #25156: add direct SPI transfer mode + * bitbang.c: Implement direct SPI transfers. + * bitbang.h: (Ditto.) + * par.c: (Ditto.) + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * term.c: Add the "spi" and "pgm" commands. + * avrdude.1: Document the changes. + * doc/avrdude.texi: (Ditto.) + +2009-02-17 Joerg Wunsch + + Submitted by Limor ("Lady Ada"): + bug #24749: add support for '328p + * avrdude.conf.in (ATmega328P): new device support. + +2009-02-17 Joerg Wunsch + + Submitted by "Womo": + bug #25241: AT90USB162, AT90USB82 device support patch for avrdude-5.5 + (also: bug #21745: AT90USBxx2 support) + * avrdude.conf.in (AT90USB162, AT90USB82): new device support. + +2009-02-17 Joerg Wunsch + + Submitted by Evangelos Arkalis: + patch #6069: Atmel AT89ISP Cable + * avrdude.conf.in (89isp): new programmer support. + +2009-02-16 Joerg Wunsch + + Submitted by Bob Paddock: + patch #6748: ATTiny88 Config + * avrdude.conf.in (ATtiny88): new device support. + +2009-02-16 Joerg Wunsch + + Submitted by Mark Litwack: + patch #6261: avrdude won't use dragon/debugwire to write a file + to eeprom + * jtagmkII.c (jtagmkII_paged_write): when in debugWire mode, + implement a paged write to EEPROM as a series of byte writes. + +2009-02-16 Joerg Wunsch + + Submitted by Janos Sallai: + patch #6542: paged_load fails on the MIB510 programming board + * stk500.c: Add a workaround for the different signon sequence on + MIB510 programmers. + +2009-02-05 Joerg Wunsch + + * avrdude.conf.in: Add the ATmega128RFA1. + * avrdude.1: document the addition of ATmega128RFA1. + * doc/avrdude.texi: (Ditto.) + diff --git a/avrdude/ChangeLog-2010 b/avrdude/ChangeLog-2010 new file mode 100644 index 00000000..45effefa --- /dev/null +++ b/avrdude/ChangeLog-2010 @@ -0,0 +1,354 @@ +2010-12-17 Joerg Wunsch + + * avrdude.conf.in (ATmega128RFA1): Bump two timing values in order to + improve ISP programming stability, in particular with the STK600. + +2010-12-14 Joerg Wunsch + + * stk500v2.c (stk500v2_command): Detect warning status codes. + +2010-10-22 Nils Springob + + * serial.h: serial_open() calls will now return -1 on error (no call to exit()) + * buspirate.c: (Dito.) + * jtagmkII.c: (Dito.) + * butterfly.c: (Dito.) + * jtagmkI.c: (Dito.) + * arduino.c: (Dito.) + * avr910.c: (Dito.) + * stk500.c: (Dito.) + * ser_avrdoper.c: (Dito.) + * stk500v2.c: (Dito.) + * ser_posix.c: (Dito.) + * usb_libusb.c: (Dito.) + +2010-07-27 Joerg Wunsch + + bug #30566: MinGW + Ubuntu 9.04 + * stk500v2.c (stk500v2_open): use same condition to refer to the AVR + Doper support as used in the definition in ser_avrdoper.c. + (Thanks to Christian Starkjohann for the analysis of the problem.) + +2010-07-19 Michal Ludvig + + * buspirate.c: Added compatibility with BusPirate "NewUI" firmware 5.x + (contributed by Kari Knuuttila) + +2010-07-12 Nils Springob + + * avrdude.conf.in (atmega88p): New device. + +2010-06-03 Joerg Wunsch + + bug #29913: 246 Byte Bug - AVRdude crashes + doc/avrdude.texi (Troubleshooting): Mention the libusb 0.1 API + wrapper issue that is present in some Linux versions. + +2010-03-19 Joerg Wunsch + + bug #29263: Can't build avrdude on windows using latest cygwin 1.7.1 + * doc/avrdude.texi: Remove the recommendation for building + Win32 binaries under Cygwin; mention MinGW as an alternative + environment. + +2010-03-08 Michal Ludvig + + * ser_posix.c(ser_set_dtr_rts): Fixed DTR on/off to make + Arduino auto-reset work. (bug #29108, patch #7100) + +2010-03-05 Joerg Wunsch + + * buspirate.c: Replace printf() by fprintf(stderr) + * safemode.c: (Dito.) + * usbtiny.c: (Dito.) + +2010-01-22 Joerg Wunsch + + Cleanup Cygwin builds. + * windows/Makefile.am (loaddrv_LDFLAGS): remove, the -mno-cygwin + flag is supposed to be set in CFLAGS by ./configure + * configure.ac: add a check for the presence of usleep(), add a + check whether the linker accepts -static + * avrdude.h: protect prototype for usleep by !defined(HAVE_USLEEP) + * ppwin.c (usleep): protect by !defined(HAVE_USLEEP) + * main.c: silence "array subscript of type char" compiler warnings + by casting all arguments to tolower()/toupper() and isspace()/ + isdigit()/ispunct() to "int" + * butterfly.c: (Dito.) + * avr910.c: (Dito.) + +2010-01-19 Joerg Wunsch + + * configure.ac: Bump for post-5.10. + +2010-01-19 Joerg Wunsch + + * configure.ac: Released version 5.10. + +2010-01-19 Joerg Wunsch + + bug #28677: Cygwin's GCC no longer supports -mno-cygwin option + * configure.ac: For Win32 environments, add a check whether the + compiler understands the -mno-cygwin option. If not, don't use + it but suggest using a different compiler. + +2010-01-18 David Hoerl + + bug #28660: Problem with loading intel hex rom files that exceed + 0x10000 bytes + * fileio.c: Fix two byte shifts. + +2010-01-15 Joerg Wunsch + + Submitted by Michael biebl: + * configure.ac: Fix FreeBSD default serial port name. + * doc/avrdude.texi: (Dito.) + +2010-01-15 Joerg Wunsch + + * jtagmkII.c: If entering JTAG mode fails with a bad JTAG ID + message, retry with external reset applied (in case the target + is in sleep mode or has asserted the JTD bit). + +2010-01-15 Joerg Wunsch + + Submitted by Aurelien Jarno: + * configure.ac: Fix build for GNU/kFreeBSD. + * ppi.c: (Dito.) + * par.c: (Dito.) + +2010-01-15 Joerg Wunsch + + * configure.ac: Bump version for post-5.8. + +2010-01-15 Joerg Wunsch + + * configure.ac: Bump version for release 5.8. + +2010-01-15 Joerg Wunsch + + Submitted by Soren Jorvang: + bug #28611: -i delay not being applied to all serial port + bit banging state transitions + * serbb_win32.c: Apply ispdelay everywhere. + * serbb_posix.c: (Dito.) + +2010-01-15 Joerg Wunsch + + * stk500v2_private.h: Implement TPI mode for AVRISPmkII/STK600 + * config_gram.y: (Dito.) + * avrpart.h: (Dito.) + * stk500v2.c: (Dito.) + * main.c: (Dito.) + * lexer.l: (Dito.) + * avrdude.conf.in: Add ATtiny4/5/9/10 + * avrdude.1: Document TPI and new device support. + * doc/avrdude.texi: (Dito.) + +2010-01-14 Joerg Wunsch + + Submitted by clint fisher: + patch #7038: Adding Atmega32U4 Device to avrdude.conf.in + * avrdude.conf.in (atmega32u4): New device. + * avrdude.1: Document the new device support. + * doc/avrdude.texi: (Dito.) + +2010-01-14 Joerg Wunsch + + Submitted by Thomas Pircher: + patch #6927: Documentation patches + * doc/avrdude.texi: Fix various typos, and remove the last + remnants of obsoleted options -i/-o/-m/-f. + * avrdude.1: Merge typo fixes from avrdude.texi where + applicable. + +2010-01-14 Joerg Wunsch + + * avrdude.1: Update documentation to match the reality (device + support, memory areas). + * doc/avrdude.texi: Update documentation to match the + reality (device support, programmer support, memory areas). + Merge buspirate-specific comments from avrdude.1. + * jtagmkII.c: Add some firmware feature checks. + +2010-01-13 Joerg Wunsch + + * jtagmkII.c: Implement PDI mode support for the JTAG ICE mkII + and the AVR Dragon. + * jtagmkII.h: (Dito.) + * config_gram.y: (Dito.) + * jtagmkII_private.h: (Dito.) + * avrdude.conf.in: (Dito.) + * lexer.l: (Dito.) + +2010-01-13 Joerg Wunsch + + * stk500v2.c: Update STK600 routing and socket card data from XML + file. + +2010-01-13 Joerg Wunsch + + * stk500v2.c: Cleanup the open/close handling to avoid accessing + unallocated memory (in the atexit handler) in case of bailing out. + * main.c: (Ditto.) + +2010-01-13 Joerg Wunsch + + * jtagmkII.c: Stylistic changes: move #defines out into + jtagmkII_private.h, drop all #if 0 blocks, fold overly long lines, + move the *_initpgm() functions to the end of the file; while being + here, remove all trailing whitespace. + * jtagmkII_private.h: move AVR32 #defines here. + +2010-01-12 Joerg Wunsch + + * bootstrap: autoconf 2.62 works well. + +2010-01-12 Joerg Wunsch + + Various fixes for Xmega devices. + * avrdude.conf.in: Correctly declare EEPROM page sizes for + all Xmega devices (0x20 instead of 0x100). + * avr.c: If a memory region has a page size declared, try + using the paged IO routines regardless of the target memory + name. Xmega EEPROM requires to be written in paged mode. + Correctly use a long (rather than unsigned long) variable to + evaluate the success status of the paged mode write attempt. + * stk500v2.c: Don't apply TIF space offsets twice (bug #27995: + AVRDUDE 5.8svn fails to program and read XMEGA); use + stk500v2_loadaddr() prior to paged mode (EEPROM and flash) writes, + otherwise programming of flash areas will fail; while being there, + check the return value of stk500v2_loadaddr() everywhere; use the + correct write/erase mode bits (same as AVR Studio does). + +2010-01-12 Michal Ludvig + + * buspirate.c: Initialise firmware version to v0.0 + prior to parsing the buspirate banner. + +2010-01-11 Joerg Wunsch + + Clean-up the Xmega erase functions. + * jtagmkII_private.h: Add CMND_XMEGA_ERASE as well as + the various XMEGA_ERASE_* definitions (from updated + appnote AVR067) + * jtagmkII.c (jtagmkII_chip_erase): Correctly implement Xmega chip + erase based on CMND_XMEGA_ERASE. After erasing an Xmega part, do + *not* reinitialize the world, as a subsequent programming + operation will fail (for unknown reasons). Actually, this was + really only required for ancient AVRs, but doesn't hurt on mega + and tiny devices. + * jtagmkII.c (jtagmkII_pre_write): Remove, this turned out + to be just a chip erase. + * jtagmkII.c (jtagmkII_program_disable): Don't try reading + "hfuse" for Xmega parts; they don't have it. + * main.c (main): Re-enable auto-erase. It's been done + before (as "jtagmkII_pre_write") in jtagmkII_paged_write() + anyway. Xmega boot and application flash areas should be + handled separately in the future, so auto_erase can only + affect the area just being programmed. + +2010-01-11 Joerg Wunsch + + * main.c (main): disable safemode for Xmega parts. + +2010-01-12 Michal Ludvig + + * buspirate.c: If the BusPirate doesn't respond + to a standard a reset command assume it was in binmode + and attempt to exit to text mode first. + +2010-01-08 Joerg Wunsch + + * bitbang.c: Fix Win32 build error: move freq up to the file + level. + * buspirate.c: Fix Win32 build warning: include to + to get a declaration for alloca(). + +2010-01-08 Thomas Fischl + + bug #28520: Programming with USBasp with low clock speed fails + * usbasp.c: Change blocksize depending on sck frequency to + avoid usb transmition timeouts. + +2010-01-08 Joerg Wunsch + + bug #27505: serbb_posix does not cope with inverted pins + * serbb_posix (serbb_highpulsepin): apply PIN_MASK when + checking pin numbers. + * serbb_win32 (serbb_highpulsepin): (Dito.) + +2010-01-08 Joerg Wunsch + + bug #28516: Linux/Dragon: Error message on exit + * stk500v2.c: Fix the "bad response to GO command: + RSP_ILLEGAL_EMULATOR_MODE" message. jtagmkII_close() + has been called with the wrong pgm->cookie. Wrap it + inside stk500v2_jtagmkII_close(), adjusting the cookie + data appropriately. + +2010-01-08 Joerg Wunsch + + Submitted by Doug: + patch #7010: Win32 enhanced bitbang_delay + * bitbang.c (bitbang_calibrate_delay, bitbang_delay): On Win32, + use the high-resolution performance counter rather than the + uneducated delay loop guess if it is available on the target + hardware. + +2010-01-08 Joerg Wunsch + + Submitted by Gerard: + patch #6828: Using arbitrary BAUD rates + * ser_posix.c (serial_baud_lookup): Allow non-standard baud + rates. + * ser_win32.c (serial_baud_lookup): (Dito.) + +2010-01-07 Joerg Wunsch + + Submitted by Eric Trein: + bug #27596: AT90s2333 is not correctly supported in avrdude.conf + * avrdude.conf.in (at90s2333): add various STK500v2 parameters. + +2010-01-07 Joerg Wunsch + + Submitted by Gyorgy Szekely: + bug #28458: Buffer line is incorrectly released for PP programmers + * par.c (par_close): use par_setmany() rather than par_setpin() + for PPI_AVR_BUFF. + +2010-01-07 Joerg Wunsch + + Submitted by Lukasz Goralczyk: + bug #27507: SIGSEGV when using avrdragon (avrdude 5.8) + * stk500v2.c (stk500v2_dragon_isp_initpgm): Use + stk500v2_jtagmkII_setup/stk500v2_jtagmkII_rather than their + jtagII counterparts, to get the private data properly + initialized. + +2010-01-07 Joerg Wunsch + + * buspirate.c: Cosmetics: remove UTF-8 dashes, adjust for 8-column + hard tabs. + +2010-01-07 Joerg Wunsch + + * buspirate.c: add $ Id $ line. + * buspirate.h: add $ Id $ line. + +2010-01-07 Joerg Wunsch + + Fix a few warnings that came up recently (some of them only triggered + by recent GCC versions). + * config_gram.y (parse_cmdbits): "brkt possibly used uninitialized" + (GCC errs here) + * jtagmkII.c (jtagmkII_reset32): "status possibly used uninitialized" + (I think GCC errs, too) + * buspirate.c: "pointers differ in signedness" (mismatch between + string processing and the use of "unsigned char" throughought the + AVRDUDE API) + +2010-01-01 Joerg Wunsch + + * jtagmkII.c (jtagmkII_smc_init32): replace sleep() by usleep() for + win32 compatibility. diff --git a/avrdude/Makefile.am b/avrdude/Makefile.am new file mode 100644 index 00000000..49a3182b --- /dev/null +++ b/avrdude/Makefile.am @@ -0,0 +1,179 @@ +# +# avrdude - A Downloader/Uploader for AVR device programmers +# Copyright (C) 2003, 2004 Theodore A. Roth +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# $Id$ +# + +EXTRA_DIST = \ + ChangeLog \ + ChangeLog-2001 \ + ChangeLog-2002 \ + ChangeLog-2003 \ + ChangeLog-2004-2006 \ + ChangeLog-2007 \ + ChangeLog-2008 \ + ChangeLog-2009 \ + avrdude.1 \ + avrdude.spec \ + bootstrap + +CLEANFILES = \ + config_gram.c \ + config_gram.h \ + lexer.c + +BUILT_SOURCES = $(CLEANFILES) + +#SUBDIRS = doc @WINDOWS_DIRS@ +#DIST_SUBDIRS = doc windows + +SUBDIRS = @SUBDIRS_AC@ +SUBDIRS += @WINDOWS_DIRS@ +DIST_SUBDIRS = @DIST_SUBDIRS_AC@ + +AM_YFLAGS = -d + +avrdude_CPPFLAGS = -DCONFIG_DIR=\"$(sysconfdir)\" + +libavrdude_a_CPPFLAGS = -DCONFIG_DIR=\"$(sysconfdir)\" + +avrdude_CFLAGS = @ENABLE_WARNINGS@ + +libavrdude_a_CFLAGS = @ENABLE_WARNINGS@ + +avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB@ @LIBUSB_1_0@ @LIBFTDI@ @LIBHID@ -lm + +bin_PROGRAMS = avrdude + +noinst_LIBRARIES = libavrdude.a + +# automake thinks these generated files should be in the distribution, +# but this might cause trouble for some users, so we rather don't want +# to have them there. +# +# See +# +# https://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=15536 +# +# for why we don't want to have them. +dist-hook: + rm -f \ + $(distdir)/lexer.c \ + $(distdir)/config_gram.c \ + $(distdir)/config_gram.h + +libavrdude_a_SOURCES = \ + config_gram.y \ + lexer.l \ + arduino.h \ + arduino.c \ + avr.c \ + avr.h \ + avr910.c \ + avr910.h \ + avrdude.h \ + avrftdi.c \ + avrftdi.h \ + avrpart.c \ + avrpart.h \ + bitbang.c \ + bitbang.h \ + buspirate.c \ + buspirate.h \ + butterfly.c \ + butterfly.h \ + config.c \ + config.h \ + confwin.c \ + confwin.h \ + crc16.c \ + crc16.h \ + fileio.c \ + fileio.h \ + freebsd_ppi.h \ + jtagmkI.c \ + jtagmkI.h \ + jtagmkI_private.h \ + jtagmkII.c \ + jtagmkII.h \ + jtagmkII_private.h \ + linux_ppdev.h \ + lists.c \ + lists.h \ + my_ddk_hidsdi.h \ + par.c \ + par.h \ + pgm.c \ + pgm.h \ + pindefs.h \ + ppi.c \ + ppi.h \ + ppiwin.c \ + safemode.c \ + safemode.h \ + serial.h \ + serbb.h \ + serbb_posix.c \ + serbb_win32.c \ + ser_avrdoper.c \ + ser_posix.c \ + ser_win32.c \ + solaris_ecpp.h \ + stk500.c \ + stk500.h \ + stk500_private.h \ + stk500v2.c \ + stk500v2.h \ + stk500v2_private.h \ + stk500generic.c \ + stk500generic.h \ + tpi.h \ + usbasp.c \ + usbasp.h \ + usbdevs.h \ + usb_libusb.c \ + usbtiny.h \ + usbtiny.c \ + update.h \ + update.c \ + wiring.h \ + wiring.c + +avrdude_SOURCES = \ + main.c \ + term.c \ + term.h + +man_MANS = avrdude.1 + +sysconf_DATA = avrdude.conf + +install-exec-local: backup-avrdude-conf + +distclean-local: + rm -f avrdude.conf + +# This will get run before the config file is installed. +backup-avrdude-conf: + @echo "Backing up avrdude.conf in ${DESTDIR}${sysconfdir}" + @if test -e ${DESTDIR}${sysconfdir}/avrdude.conf; then \ + cp -pR ${DESTDIR}${sysconfdir}/avrdude.conf \ + ${DESTDIR}${sysconfdir}/avrdude.conf.bak; \ + fi diff --git a/avrdude/NEWS b/avrdude/NEWS new file mode 100644 index 00000000..c83a41d5 --- /dev/null +++ b/avrdude/NEWS @@ -0,0 +1,572 @@ +$Id$ + +Approximate change log for AVRDUDE by version. + +(For more detailed changes, see the ChangeLog file.) + +---------------------------------------------------------------------- +Current: + + * New devices supported: + - ATmega88P/168P + - ATmega8U2/16U2/32U2 + - ATtiny4313 + + * New programmers supported: + - TPI programming through bitbang programmers (both, serial + and parallel ones) + - FT2232 (and relatives) based programmers (MPSSE bitbang mode) + - Wiring environment (http://wiring.org.co/) + - butterfly-style bootloader of the Mikrokopter.de device + + * Bugfixes + + +Version 5.10: + + * Bugfixes + - bug #28660: Problem with loading intel hex rom files that exceed + 0x10000 bytes + - see ChangeLog for further details + + * New Features + - (JTAG ICE / AVR Dragon) apply external reset if JTAG ID could + not be read + +Version 5.9: + + * New devices supported: + + - AVR32A0512 (JTAGMKII only) + - ATmega32U4 + - ATtiny4 + - ATtiny5 + - ATtiny9 + - ATtiny10 + + * New programmers supported: + + - BusPirate + - Arduino + - JTAGICEmkII and AVR Dragon in PDI mode (ATxmega devices) + - STK600 and AVRISP mkII in TPI mode (ATtiny4/5/9/10) + + * Bugfixes + + - see ChangeLog and ChangeLog-2009 for details + +Version 5.8: + + * Bugfixes; most importantly, fix a serious memory corruption for + that JTAG ICE mkII and AVR Dragon in ISP/HVSP/PP mode. + +Version 5.7: + + * New devices supported: + + - ATXMEGA64A1 + - ATXMEGA192A1 + - ATXMEGA256A1 + - ATXMEGA64A3 + - ATXMEGA128A3 + - ATXMEGA192A3 + - ATXMEGA256A3 + - ATXMEGA256A3B + - ATXMEGA16A4 + - ATXMEGA32A4 + - ATXMEGA64A4 + - ATXMEGA128A4 + + * Major Xmega fixes for the JTAG ICE mkII (patch #6825) + + * Bugfixes. + +Version 5.6: + + * New devices supported: + + - AT90USB82 + - AT90USB162 + - ATtiny88 + - ATmega328P + - ATmega1284P + - ATmega128RFA1 + - ATxmega128A1 rev D + - ATxmega128A1 + - ATxmega256A3 + + * New programmers supported: + + - AT89ISP cable (patch #6069) + - Arduino + + * Add support for the -x option to pass extended parameters to the + programmer backend. + + * Add support for JTAG daisy-chains, using the -x daisychain= + option. + + * Add support for the Atmel STK600 for "classic" AVRs (AT90, ATtiny, + ATmega), using either ISP or high-voltage programming modes. + + * Add support for the -x devcode extended parameter to the avr910 + programmer, to allow overriding the device code sent to the + programmer. + + * Add support for the Crossbow MIB510 programmer (patch #6074, #6542). + + * Add support to bootstrap with GNU autoconf 2.61, and automake 1.10, + respectively. + + * Add support for ATxmega128A1 (including the revision D engineering + samples) for STK600 and AVRISPmkII tools using PDI + + * The option combination -tF now enters terminal mode even if the + device initialization failed, so the user can modify programmer + parameters (like Vtarget). + + * Add preliminary support for ATxmega128A1 for the JTAG ICE mkII using + JTAG. + + * Add support for direct SPI transfers (bug #25156). + + * Bugfixes. + +Version 5.5: + + * Add support for the USBtinyISP programmer (patch #6233) + + * Add support for the C2N232I serial bitbang programmer (patch #6121) + + * Bugfixes. + +Version 5.4: + + * New devices supported: + + - AT90PWM2B/AT90PWM3B + + * Bugfixes. + + * Source code rearranged so that the functionality is now built + into a libavrdude.a library where main.c is currently the only + existing frontend. + + * Implement ATmega256x support for butterfly/avr109. + +Version 5.3.1: + + * Add support for the AVR Dragon (all modes: ISP, JTAG, HVSP, PP, + debugWire). + + * Add support for debugWire (both, JTAG ICE mkII, and AVR Dragon). + + * Add support for the AVR Doper USB HID-class programmer. + + * Bugfixes. + +Version 5.2: + + * New devices supported: + + - AT90USB646/647/1286/1287 + - ATmega2560/2561 + - ATmega325/3250/645/6450 + - ATtiny11 (HVSP only device) + - ATtiny261/461/861 + + * Fixed paged flash write operations for AT90PWMx devices + (error in datasheet). + + * Add signature verification. + + * Add high-voltage mode programming for the STK500 (both, + parallel, and high-voltage serial programming). + + * Add support for using the JTAG ICE mkII as a generic ISP + programmer. + + * Allow for specifying the ISP clock delay as an option for + bit-bang programming adapters. + + * Add support for Thomas Fischl's USBasp low-cost USB-attached + programmer. + + * The "stk500" programmer type is now implemented as a stub + that tries to probe for either "stk500v1" or "stk500v2". + + * Many bugfixes. + +Version 5.1: + + * New devices supported: + + - ATmega640/1280/1281 + - ATtiny24/44/84 + + * JTAG mkII support now works with libusb-win32, too + + * JTAG ICE mkI support has been added + + * Solaris support has been added (including ecpp(7D) parallel-port + bit-bang mode) + + +Version 5.0: + + * Support for JTAGICE MkII device + + * Support for STK500 Version 2 Protocol + + * New devices supported: + + - AT90CAN128 + - ATmega329x/649x + - ATmega164/324/644 + - AT90PWM2/3, + - ATmega164/324/644 + - ATmega329x/649x + - ATtiny25/45/85 + + * Support for serial bit-bang adapters: Ponyprog serial, UISP DASA, + UISP DASA3. + + * DAPA programmer pinout supported + + * New "safemode" feature where fuse bits are verified before exit + and if possible recovered if they have changed. This is intended + to protect against changed fuses which were not requested which is + reported to sometimes happen due to improper power supply or other + reasons. + + * Various fixes for avr910 and butterfly programmers + + * Full support for AVR109 boot loaders (butterfly) + + * Adding -q -q suppresses most terminal output + + +Version 4.4.0: + + * Native Win32 support: The windows build doesn't need Cygwin + anymore. Additionally, the delay timing on windows should be + more accurate now. + Contributed by Martin Thomas + + * Add support for + - ATmega48, ATmega88 (contributed by Galen Seitz) + - ATtiny2313 (contributed by Bob Paddock) + - ATtiny13 (contributed by Pawel Moll) + + * Added command to change the SCK of STK500-programmers. Now it + is possible to program uC with slow oscillator. + Contributed by Galen Seitz + + * Baudrate for serial programmers (STK500 and AVR910) is + configurable in the config or at the command-line. + This way some more tweaked bootloaders and programmers can be used. + + * Deprecated options have been removed. + Now the "-U" option must be used. + + * MacOS X now supported by default. + +Version 4.3.0: + + * Added support for "Butterfly" evaluation board. + + * Make cycle-count work with AVR910-programmers. + + * Added "Troubleshooting"-Appendix to the manual. + + * Add ATmega8515 support. + Contributed by: Matthias Weißer + + * Add ATmega64 support. + Contributed by: Erik Christiansen + + * Improved polling algorithm to speed up + programming of byte oriented parallel programmers. + Contributed by: Jan-Hinnerk Reichert + + * Add "fuse" and "lock" definitions for the AT90S8535. + + * STK500 skips empty pages in paged write resulting in faster downloads + when there are empty blocks in between code (such as files that contain + application code and bootloader code). + +Version 4.2.0: + + * Add basic support for reading and writing fuses via SPI with avr910 + programmers. Submitted by + Jan-Hinnerk Reichert . + + * Perform an auto erase before programming if the flash memory is + anywhere specified to be written by any of the -U requests. Old + style memory specification options (-f, -i, -I, -m, and -o) are + deprecated in favor of the new -U options. Auto erase is disabled + if any of the old-style options (specifically -i and -o) are + specified. + + * Add new -U option for specifying programming operations - allows + multiple memory operations on a single command line. + + * New progress reporting, looks nicer and is nicer to wrapper + environments such as emacs. + + * Fix long-standing timing (verify) problems on Windows platform. + Submitted by Alex Shepherd . + + * Add new file format option - 'm' for "immediate mode." In this + case, the filename argument of the -o, -i, or -U options is + treated as the data for uploading - useful for specifying fuse + bits without having to create a single-byte file for uploading. + + * Add support for displaying and setting the various STK500 operational + parameters (Vtarget, Varef, Master clock). + + * Add 'picoweb' programming cable programmer. + Contributed by Rune Christensen . + + * Add support for the sp12 programmer. Submitted by + Larry Barello . + + +Version 4.1.0 + + * Add support for the Bascom SAMPLE programmer. Submitted by + Larry Barello . + + * Add support for avr910 type programmers (mcu00100, pavr avr910, etc). + + * Support new devices: ATmega8535, ATtiny26 + + +Version 4.0.0 + + * Now support Linux - added by "Theodore A. Roth" . + + * Now support Windows - added by "Eric B. Weddington" . + + * Use 'configure' scripts to tailor the code to the system avrdude + is getting ready to be compiled on - added by "Theodore A. Roth" + . + + * Motorola S-Record support - submitted by "Alexey V.Levdikov " + . + + * Support parallel programming on the STK500. Introduce 'pagel' and + 'bs2' keywords to the config file for this purpose. + + * Add support for the AT90S2343 + + * Add support for the ATmega169 + + * Add ability to specify system defaults within the config file + (default parallel port, default serial port). + + * Specify the default programmer seperately from the programmer + definition. This is now done in the config file using the + 'default_programmer' keyword. + + * Support a per-user config file (~/.avrduderc) so that one can + override system wide defaults if desired. + + * Follow the datasheet more closely for several parts in the "retry" + code when entering programming mode fails initially. Introduce + 'retry_pulse' to the config file for this purpose. + + + +Version 3.1.0 + + * This change represents a name change only. There is currently an + effort to port AVRPROG to other platforms including Linux and + Windows. Since Atmel's programmer binary that's included within + their AVR Studio software is named AVRPROG.EXE on the Windows OS, + there is the chance for confusion if we keep calling this program + AVRPROG as well. Up until now the name hasn't really been a + problem since there was no chance to confuse 'avrprog' on Unix + with Atmel's AVRPROG because Atmel's tools only run on Windows. + But with the Unix 'avrprog' possibly being ported to Windows, I + felt a name change was the best way to avoid problems. + + So - from this point forward, my FreeBSD Unix program formerly + known as AVRPROG will subsequently be known as AVRDUDE (AVR + Downloader/UploaDEr). + + This change also represents a time when the AVRDUDE sources move + from my own private repository to a public repository. This will + give other developers a chance to port AVRDUDE to other platforms + and extend its functionality to support additional programming + hardware, etc. + + So goodbye AVRPROG, welcome AVRDUDE! + +Version 3.0.0 + + * Rewrite parts of the code to make it easy to support other types + of programmers besides the directly connected parallel port + programmer (PPI). + + * Add support for Atmel's STK500 programmer/development board. The + STK500's "paged mode" read/write is supported which makes this + programmer very fast. This is sorely needed on parts with large + memories such as the ATmega128. My 12K test program burns in + about 5 seconds, add another 5 to read it back out for + verification. + + +Version 2.1.5: + + * When getting ready to initiate communications with the AVR device, + first pull /RESET low for a short period of time before enabling + the buffer chip. This sequence allows the AVR to be reset before + the buffer is enabled to avoid a short period of time where the + AVR may be driving the programming lines at the same time the + programmer tries to. Of course, if a buffer is being used, then + the /RESET line from the programmer needs to be directly connected + to the AVR /RESET line and not via the buffer chip. + + Feature contributed by Rick C. Petty . + + * When in interactive terminal mode and dumping memory using the + 'dump ' command without any address information, and the + end of memory is reached, wrap back around to zero on the next + invocation. + + +Version 2.1.4: + + * Fix -Y option. + + +Version 2.1.3: + + * Be backward compatible when reading 2-byte rewrite cycle counters + as written by avrprog version 2.1.0. Version 2.1.1 changed over + to a 4-byte counter, which caused avrprog versions 2.1.1 and 2.1.2 + to report a negative count for parts that were initialized using + version 2.1.0. Thanks to Joerg Wunsch for noticing this. + + +Version 2.1.2: + + * Add '-V' option to disable automatic verify check with uploading + data. + + +Version 2.1.1: + + * Fix ATmega128 instruction sequences for reading fuse bits - + contributed by Joerg Wunsch. + + * Modify erase-rewrite cycle counter code to use a 4 byte counter + instead of a two byte counter. + + +Version 2.1.0: + + * Implement a per-part erase-rewrite cycle counter; requires the use + of two bytes of EEPROM memory. + + +Version 2.0.5: + + * Support for ATtiny15 - contributed by Asher Hoskins + + +Version 2.0.4: + + * Config file fixes for various parts. + + +Version 2.0.3: + + * Work around problem programming fuse bits on parts like the + at90s4433 as described in the following errata: + + http://www.atmel.com/atmel/acrobat/doc1280.pdf + + * Add part definition for at90s4414, at90s4433. + + * Add fuse/lock bit memory instructions for the at90s1200, + at90s2333, at90s4433 and at90s8515. + + * Fix setting of programmer status LEDs under certain write-fail + conditions. + + +Version 2.0.2 : + + * Fix writing to read-only memories such as the lock bits of the + AT90S2313. + + * Copyright updates. + + +Version 2.0.1 : + + * Use correct parallel port pins for VCC. + + * Add programmer definition for Atmel's STK200. + + * Add programmer definition for the AVR3 board. + + * Fix address bit encoding for many parts. + + * Allow the ``BUFF'' signal to be asserted by multiple pins of the + parallel port (like VCC) instead of just one. The STK200 appears + to need this feature. + + +Version 2.0.0 : + + * Add support for programming fuse and lock bits if supported by the + part. + + * Move instruction encoding into the config file. Now any part can + be supported as long as it uses the same basic serial programming + instruction format. + + * Add part definitions for the ATMega163 and ATMega8 devices. + + +Version 1.4.3 : + + * Mostly internal code cleanup. + + +Version 1.4.2 : + + * Fixes for ATMega paged memory support. + + * Support for ATMega16 device. + + +Version 1.4.1 : + + * No functional changes, update to Copyrights only. + + +Version 1.4.0 : + + * Add part definitions to the config file. + + * Add initial support for Atmel's ATMega paged memory parts. + + * Config file documentation added. + + * Add a definition for the Dontronics DT006 programmer. + + * Fix Intel Hex support for addresses larger than 64k. + + +Version 1.3.0 : + + * Make programmer pin assignments configurable. + + +Version 1.2.2 : + + * Initial public release. diff --git a/avrdude/README b/avrdude/README new file mode 100644 index 00000000..ec04fb58 --- /dev/null +++ b/avrdude/README @@ -0,0 +1,6 @@ +See the documentation file for the details. + +The latest version of AVRDUDE is always available here: + + http://savannah.nongnu.org/projects/avrdude + diff --git a/avrdude/arduino.c b/avrdude/arduino.c new file mode 100644 index 00000000..123e83e8 --- /dev/null +++ b/avrdude/arduino.c @@ -0,0 +1,131 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2009 Lars Immisch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Arduino programmer + * + * The Arduino programmer is mostly a STK500v1, just the signature bytes + * are read differently. + */ + +#include "ac_cfg.h" + +#include +#include +#include + +#include "avrdude.h" +#include "pgm.h" +#include "stk500_private.h" +#include "stk500.h" +#include "serial.h" + +/* read signature bytes - arduino version */ +static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) +{ + unsigned char buf[32]; + + /* Signature byte reads are always 3 bytes. */ + + if (m->size < 3) { + fprintf(stderr, "%s: memsize too small for sig byte read", progname); + return -1; + } + + buf[0] = Cmnd_STK_READ_SIGN; + buf[1] = Sync_CRC_EOP; + + serial_send(&pgm->fd, buf, 2); + + if (serial_recv(&pgm->fd, buf, 5) < 0) + return -1; + if (buf[0] == Resp_STK_NOSYNC) { + fprintf(stderr, "%s: stk500_cmd(): programmer is out of sync\n", + progname); + return -1; + } else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: arduino_read_sig_bytes(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -2; + } + if (buf[4] != Resp_STK_OK) { + fprintf(stderr, + "\n%s: arduino_read_sig_bytes(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_OK, buf[4]); + return -3; + } + + m->buf[0] = buf[1]; + m->buf[1] = buf[2]; + m->buf[2] = buf[3]; + + return 3; +} + +static int arduino_open(PROGRAMMER * pgm, char * port) +{ + strcpy(pgm->port, port); + if (serial_open(port, pgm->baudrate? pgm->baudrate: 115200, &pgm->fd)==-1) { + return -1; + } + + /* Clear DTR and RTS to unload the RESET capacitor + * (for example in Arduino) */ + serial_set_dtr_rts(&pgm->fd, 0); + usleep(50*1000); + /* Set DTR and RTS back to high */ + serial_set_dtr_rts(&pgm->fd, 1); + usleep(50*1000); + + /* + * drain any extraneous input + */ + stk500_drain(pgm, 0); + + if (stk500_getsync(pgm) < 0) + return -1; + + return 0; +} + +static void arduino_close(PROGRAMMER * pgm) +{ + serial_set_dtr_rts(&pgm->fd, 0); + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + +void arduino_initpgm(PROGRAMMER * pgm) +{ + /* This is mostly a STK500; just the signature is read + differently than on real STK500v1 + and the DTR signal is set when opening the serial port + for the Auto-Reset feature */ + stk500_initpgm(pgm); + + strcpy(pgm->type, "Arduino"); + pgm->read_sig_bytes = arduino_read_sig_bytes; + pgm->open = arduino_open; + pgm->close = arduino_close; +} diff --git a/avrdude/arduino.h b/avrdude/arduino.h new file mode 100644 index 00000000..a5819ee1 --- /dev/null +++ b/avrdude/arduino.h @@ -0,0 +1,29 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2009 Lars Immisch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef arduino_h__ +#define arduino_h__ + +void arduino_initpgm (PROGRAMMER * pgm); + +#endif + + diff --git a/avrdude/avr.c b/avrdude/avr.c new file mode 100644 index 00000000..09dab1fe --- /dev/null +++ b/avrdude/avr.c @@ -0,0 +1,1031 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * Copyright (C) 2011 Darell Tan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" + +#include "avr.h" +#include "lists.h" +#include "pindefs.h" +#include "ppi.h" +#include "safemode.h" +#include "update.h" +#include "tpi.h" + +FP_UpdateProgress update_progress; + +#define DEBUG 0 + +/* TPI: returns 1 if NVM controller busy, 0 if free */ +int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm) +{ + unsigned char cmd; + unsigned char res; + int rc = 0; + + cmd = TPI_CMD_SIN | TPI_SIO_ADDR(TPI_IOREG_NVMCSR); + rc = pgm->cmd_tpi(pgm, &cmd, 1, &res, 1); + return (rc & TPI_IOREG_NVMCSR_NVMBSY); +} + +/* TPI: setup NVMCMD register and pointer register (PR) for read/write/erase */ +static int avr_tpi_setup_rw(PROGRAMMER * pgm, AVRMEM * mem, + unsigned long addr, unsigned char nvmcmd) +{ + unsigned char cmd[4]; + int rc; + + /* set NVMCMD register */ + cmd[0] = TPI_CMD_SOUT | TPI_SIO_ADDR(TPI_IOREG_NVMCMD); + cmd[1] = nvmcmd; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + if (rc == -1) + return -1; + + /* set Pointer Register (PR) */ + cmd[0] = TPI_CMD_SSTPR | 0; + cmd[1] = (mem->offset + addr) & 0xFF; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + if (rc == -1) + return -1; + + cmd[0] = TPI_CMD_SSTPR | 1; + cmd[1] = ((mem->offset + addr) >> 8) & 0xFF; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + if (rc == -1) + return -1; + + return 0; +} + +int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + unsigned char cmd[4]; + unsigned char res[4]; + unsigned char data; + int r; + OPCODE * readop, * lext; + + if (pgm->cmd == NULL) { + fprintf(stderr, + "%s: Error: %s programmer uses avr_read_byte_default() but does not\n" + "provide a cmd() method.\n", + progname, pgm->type); + return -1; + } + + pgm->pgm_led(pgm, ON); + pgm->err_led(pgm, OFF); + + if (p->flags & AVRPART_HAS_TPI) { + if (pgm->cmd_tpi == NULL) { + fprintf(stderr, "%s: Error: %s programmer does not support TPI\n", + progname, pgm->type); + return -1; + } + + while (avr_tpi_poll_nvmbsy(pgm)); + + /* setup for read */ + avr_tpi_setup_rw(pgm, mem, addr, TPI_NVMCMD_NO_OPERATION); + + /* load byte */ + cmd[0] = TPI_CMD_SLD; + r = pgm->cmd_tpi(pgm, cmd, 1, value, 1); + if (r == -1) + return -1; + + return 0; + } + + /* + * figure out what opcode to use + */ + if (mem->op[AVR_OP_READ_LO]) { + if (addr & 0x00000001) + readop = mem->op[AVR_OP_READ_HI]; + else + readop = mem->op[AVR_OP_READ_LO]; + addr = addr / 2; + } + else { + readop = mem->op[AVR_OP_READ]; + } + + if (readop == NULL) { +#if DEBUG + fprintf(stderr, + "avr_read_byte(): operation not supported on memory type \"%s\"\n", + p->desc); +#endif + return -1; + } + + /* + * If this device has a "load extended address" command, issue it. + */ + lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + if (lext != NULL) { + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr); + pgm->cmd(pgm, cmd, res); + } + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(readop, cmd); + avr_set_addr(readop, cmd, addr); + pgm->cmd(pgm, cmd, res); + data = 0; + avr_get_output(readop, res, &data); + + pgm->pgm_led(pgm, OFF); + + *value = data; + + return 0; +} + + +/* + * Return the number of "interesting" bytes in a memory buffer, + * "interesting" being defined as up to the last non-0xff data + * value. This is useful for determining where to stop when dealing + * with "flash" memory, since writing 0xff to flash is typically a + * no-op. Always return an even number since flash is word addressed. + */ +int avr_mem_hiaddr(AVRMEM * mem) +{ + int i, n; + + /* return the highest non-0xff address regardless of how much + memory was read */ + for (i=mem->size-1; i>0; i--) { + if (mem->buf[i] != 0xff) { + n = i+1; + if (n & 0x01) + return n+1; + else + return n; + } + } + + return 0; +} + + +/* + * Read the entirety of the specified memory type into the + * corresponding buffer of the avrpart pointed to by 'p'. If size = + * 0, read the entire contents, otherwise, read 'size' bytes. + * + * Return the number of bytes read, or < 0 if an error occurs. + */ +int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose) +{ + unsigned char rbyte; + unsigned long i; + unsigned char * buf; + unsigned char cmd[4]; + AVRMEM * mem; + int rc; + + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, "No \"%s\" memory for part %s\n", + memtype, p->desc); + return -1; + } + + buf = mem->buf; + if (size == 0) { + size = mem->size; + } + + /* + * start with all 0xff + */ + memset(buf, 0xff, size); + + /* supports "paged load" thru post-increment */ + if ((p->flags & AVRPART_HAS_TPI) && mem->page_size != 0) { + if (pgm->cmd_tpi == NULL) { + fprintf(stderr, "%s: Error: %s programmer does not support TPI\n", + progname, pgm->type); + return -1; + } + + while (avr_tpi_poll_nvmbsy(pgm)); + + /* setup for read (NOOP) */ + avr_tpi_setup_rw(pgm, mem, 0, TPI_NVMCMD_NO_OPERATION); + + /* load bytes */ + for (i = 0; i < size; i++) { + cmd[0] = TPI_CMD_SLD_PI; + rc = pgm->cmd_tpi(pgm, cmd, 1, &buf[i], 1); + if (rc == -1) { + fprintf(stderr, "avr_read(): error reading address 0x%04lx\n", i); + return -1; + } + + report_progress(i, size, NULL); + } + return avr_mem_hiaddr(mem); + } + + if (pgm->paged_load != NULL && mem->page_size != 0) { + /* + * the programmer supports a paged mode read, perhaps more + * efficiently than we can read it directly, so use its routine + * instead + */ + rc = pgm->paged_load(pgm, p, mem, mem->page_size, size); + if (rc >= 0) { + if (strcasecmp(mem->desc, "flash") == 0) + return avr_mem_hiaddr(mem); + else + return rc; + } + } + + if (strcmp(mem->desc, "signature") == 0) { + if (pgm->read_sig_bytes) { + return pgm->read_sig_bytes(pgm, p, mem); + } + } + + for (i=0; iread_byte(pgm, p, mem, i, &rbyte); + if (rc != 0) { + fprintf(stderr, "avr_read(): error reading address 0x%04lx\n", i); + if (rc == -1) + fprintf(stderr, + " read operation not supported for memory \"%s\"\n", + memtype); + return -2; + } + buf[i] = rbyte; + report_progress(i, size, NULL); + } + + if (strcasecmp(mem->desc, "flash") == 0) + return avr_mem_hiaddr(mem); + else + return i; +} + + +/* + * write a page data at the specified address + */ +int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr) +{ + unsigned char cmd[4]; + unsigned char res[4]; + OPCODE * wp, * lext; + + if (pgm->cmd == NULL) { + fprintf(stderr, + "%s: Error: %s programmer uses avr_write_page() but does not\n" + "provide a cmd() method.\n", + progname, pgm->type); + return -1; + } + + wp = mem->op[AVR_OP_WRITEPAGE]; + if (wp == NULL) { + fprintf(stderr, + "avr_write_page(): memory \"%s\" not configured for page writes\n", + mem->desc); + return -1; + } + + /* + * if this memory is word-addressable, adjust the address + * accordingly + */ + if ((mem->op[AVR_OP_LOADPAGE_LO]) || (mem->op[AVR_OP_READ_LO])) + addr = addr / 2; + + pgm->pgm_led(pgm, ON); + pgm->err_led(pgm, OFF); + + /* + * If this device has a "load extended address" command, issue it. + */ + lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + if (lext != NULL) { + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr); + pgm->cmd(pgm, cmd, res); + } + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(wp, cmd); + avr_set_addr(wp, cmd, addr); + pgm->cmd(pgm, cmd, res); + + /* + * since we don't know what voltage the target AVR is powered by, be + * conservative and delay the max amount the spec says to wait + */ + usleep(mem->max_write_delay); + + pgm->pgm_led(pgm, OFF); + return 0; +} + + +int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + unsigned char cmd[4]; + unsigned char res[4]; + unsigned char r; + int ready; + int tries; + unsigned long start_time; + unsigned long prog_time; + unsigned char b; + unsigned short caddr; + OPCODE * writeop; + int rc; + int readok=0; + struct timeval tv; + + if (pgm->cmd == NULL) { + fprintf(stderr, + "%s: Error: %s programmer uses avr_write_byte_default() but does not\n" + "provide a cmd() method.\n", + progname, pgm->type); + return -1; + } + + if (p->flags & AVRPART_HAS_TPI) { + if (pgm->cmd_tpi == NULL) { + fprintf(stderr, "%s: Error: %s programmer does not support TPI\n", + progname, pgm->type); + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) { + fprintf(stderr, "Writing a byte to flash is not supported for %s\n", p->desc); + return -1; + } else if ((mem->offset + addr) & 1) { + fprintf(stderr, "Writing a byte to an odd location is not supported for %s\n", p->desc); + return -1; + } + + while (avr_tpi_poll_nvmbsy(pgm)); + + /* must erase fuse first */ + if (strcmp(mem->desc, "fuse") == 0) { + /* setup for SECTION_ERASE (high byte) */ + avr_tpi_setup_rw(pgm, mem, addr | 1, TPI_NVMCMD_SECTION_ERASE); + + /* write dummy byte */ + cmd[0] = TPI_CMD_SST; + cmd[1] = 0xFF; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + + while (avr_tpi_poll_nvmbsy(pgm)); + } + + /* setup for WORD_WRITE */ + avr_tpi_setup_rw(pgm, mem, addr, TPI_NVMCMD_WORD_WRITE); + + cmd[0] = TPI_CMD_SST_PI; + cmd[1] = data; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + /* dummy high byte to start WORD_WRITE */ + cmd[0] = TPI_CMD_SST_PI; + cmd[1] = data; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + + while (avr_tpi_poll_nvmbsy(pgm)); + + return 0; + } + + if (!mem->paged) { + /* + * check to see if the write is necessary by reading the existing + * value and only write if we are changing the value; we can't + * use this optimization for paged addressing. + */ + rc = pgm->read_byte(pgm, p, mem, addr, &b); + if (rc != 0) { + if (rc != -1) { + return -2; + } + /* + * the read operation is not support on this memory type + */ + } + else { + readok = 1; + if (b == data) { + return 0; + } + } + } + + /* + * determine which memory opcode to use + */ + if (mem->op[AVR_OP_WRITE_LO]) { + if (addr & 0x01) + writeop = mem->op[AVR_OP_WRITE_HI]; + else + writeop = mem->op[AVR_OP_WRITE_LO]; + caddr = addr / 2; + } + else if (mem->paged && mem->op[AVR_OP_LOADPAGE_LO]) { + if (addr & 0x01) + writeop = mem->op[AVR_OP_LOADPAGE_HI]; + else + writeop = mem->op[AVR_OP_LOADPAGE_LO]; + caddr = addr / 2; + } + else { + writeop = mem->op[AVR_OP_WRITE]; + caddr = addr; + } + + if (writeop == NULL) { +#if DEBUG + fprintf(stderr, + "avr_write_byte(): write not supported for memory type \"%s\"\n", + mem->desc); +#endif + return -1; + } + + + pgm->pgm_led(pgm, ON); + pgm->err_led(pgm, OFF); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(writeop, cmd); + avr_set_addr(writeop, cmd, caddr); + avr_set_input(writeop, cmd, data); + pgm->cmd(pgm, cmd, res); + + if (mem->paged) { + /* + * in paged addressing, single bytes to be written to the memory + * page complete immediately, we only need to delay when we commit + * the whole page via the avr_write_page() routine. + */ + pgm->pgm_led(pgm, OFF); + return 0; + } + + if (readok == 0) { + /* + * read operation not supported for this memory type, just wait + * the max programming time and then return + */ + usleep(mem->max_write_delay); /* maximum write delay */ + pgm->pgm_led(pgm, OFF); + return 0; + } + + tries = 0; + ready = 0; + while (!ready) { + + if ((data == mem->readback[0]) || + (data == mem->readback[1])) { + /* + * use an extra long delay when we happen to be writing values + * used for polled data read-back. In this case, polling + * doesn't work, and we need to delay the worst case write time + * specified for the chip. + */ + usleep(mem->max_write_delay); + rc = pgm->read_byte(pgm, p, mem, addr, &r); + if (rc != 0) { + pgm->pgm_led(pgm, OFF); + pgm->err_led(pgm, OFF); + return -5; + } + } + else { + gettimeofday (&tv, NULL); + start_time = (tv.tv_sec * 1000000) + tv.tv_usec; + do { + /* + * Do polling, but timeout after max_write_delay. + */ + rc = pgm->read_byte(pgm, p, mem, addr, &r); + if (rc != 0) { + pgm->pgm_led(pgm, OFF); + pgm->err_led(pgm, ON); + return -4; + } + gettimeofday (&tv, NULL); + prog_time = (tv.tv_sec * 1000000) + tv.tv_usec; + } while ((r != data) && + ((prog_time-start_time) < mem->max_write_delay)); + } + + /* + * At this point we either have a valid readback or the + * max_write_delay is expired. + */ + + if (r == data) { + ready = 1; + } + else if (mem->pwroff_after_write) { + /* + * The device has been flagged as power-off after write to this + * memory type. The reason we don't just blindly follow the + * flag is that the power-off advice may only apply to some + * memory bits but not all. We only actually power-off the + * device if the data read back does not match what we wrote. + */ + pgm->pgm_led(pgm, OFF); + fprintf(stderr, + "%s: this device must be powered off and back on to continue\n", + progname); + if (pgm->pinno[PPI_AVR_VCC]) { + fprintf(stderr, "%s: attempting to do this now ...\n", progname); + pgm->powerdown(pgm); + usleep(250000); + rc = pgm->initialize(pgm, p); + if (rc < 0) { + fprintf(stderr, "%s: initialization failed, rc=%d\n", progname, rc); + fprintf(stderr, + "%s: can't re-initialize device after programming the " + "%s bits\n", progname, mem->desc); + fprintf(stderr, + "%s: you must manually power-down the device and restart\n" + "%s: %s to continue.\n", + progname, progname, progname); + return -3; + } + + fprintf(stderr, "%s: device was successfully re-initialized\n", + progname); + return 0; + } + } + + tries++; + if (!ready && tries > 5) { + /* + * we wrote the data, but after waiting for what should have + * been plenty of time, the memory cell still doesn't match what + * we wrote. Indicate a write error. + */ + pgm->pgm_led(pgm, OFF); + pgm->err_led(pgm, ON); + + return -6; + } + } + + pgm->pgm_led(pgm, OFF); + return 0; +} + + +/* + * write a byte of data at the specified address + */ +int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + + unsigned char safemode_lfuse; + unsigned char safemode_hfuse; + unsigned char safemode_efuse; + unsigned char safemode_fuse; + + /* If we write the fuses, then we need to tell safemode that they *should* change */ + safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse); + + if (strcmp(mem->desc, "fuse")==0) { + safemode_fuse = data; + } + if (strcmp(mem->desc, "lfuse")==0) { + safemode_lfuse = data; + } + if (strcmp(mem->desc, "hfuse")==0) { + safemode_hfuse = data; + } + if (strcmp(mem->desc, "efuse")==0) { + safemode_efuse = data; + } + + safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse); + + return pgm->write_byte(pgm, p, mem, addr, data); +} + + +/* + * Write the whole memory region of the specified memory from the + * corresponding buffer of the avrpart pointed to by 'p'. Write up to + * 'size' bytes from the buffer. Data is only written if the new data + * value is different from the existing data value. Data beyond + * 'size' bytes is not affected. + * + * Return the number of bytes written, or -1 if an error occurs. + */ +int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose) +{ + int rc; + int wsize; + long i; + unsigned char data; + int werror; + unsigned char cmd[4]; + AVRMEM * m; + + m = avr_locate_mem(p, memtype); + if (m == NULL) { + fprintf(stderr, "No \"%s\" memory for part %s\n", + memtype, p->desc); + return -1; + } + + pgm->err_led(pgm, OFF); + + werror = 0; + + wsize = m->size; + if (size < wsize) { + wsize = size; + } + else if (size > wsize) { + fprintf(stderr, + "%s: WARNING: %d bytes requested, but memory region is only %d" + "bytes\n" + "%sOnly %d bytes will actually be written\n", + progname, size, wsize, + progbuf, wsize); + } + + + if ((p->flags & AVRPART_HAS_TPI) && m->page_size != 0) { + if (pgm->cmd_tpi == NULL) { + fprintf(stderr, + "%s: Error: %s programmer does not support TPI\n", + progname, pgm->type); + return -1; + } + + while (avr_tpi_poll_nvmbsy(pgm)); + + /* setup for WORD_WRITE */ + avr_tpi_setup_rw(pgm, m, 0, TPI_NVMCMD_WORD_WRITE); + + /* make sure it's aligned to a word boundary */ + if (wsize & 0x1) { + wsize++; + } + + /* write words, low byte first */ + for (i = 0; i < wsize; i++) { + cmd[0] = TPI_CMD_SST_PI; + cmd[1] = m->buf[i]; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + + cmd[1] = m->buf[++i]; + rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0); + + while (avr_tpi_poll_nvmbsy(pgm)); + report_progress(i, wsize, NULL); + } + return i; + } + + if (pgm->paged_write != NULL && m->page_size != 0) { + /* + * the programmer supports a paged mode write, perhaps more + * efficiently than we can read it directly, so use its routine + * instead + */ + if ((i = pgm->paged_write(pgm, p, m, m->page_size, size)) >= 0) + return i; + } + + if (pgm->write_setup) { + pgm->write_setup(pgm, p, m); + } + + for (i=0; ibuf[i]; + report_progress(i, wsize, NULL); + + rc = avr_write_byte(pgm, p, m, i, data); + if (rc) { + fprintf(stderr, " ***failed; "); + fprintf(stderr, "\n"); + pgm->err_led(pgm, ON); + werror = 1; + } + + if (m->paged) { + /* + * check to see if it is time to flush the page with a page + * write + */ + if (((i % m->page_size) == m->page_size-1) || + (i == wsize-1)) { + rc = avr_write_page(pgm, p, m, i); + if (rc) { + fprintf(stderr, + " *** page %ld (addresses 0x%04lx - 0x%04lx) failed " + "to write\n", + i % m->page_size, + i - m->page_size + 1, i); + fprintf(stderr, "\n"); + pgm->err_led(pgm, ON); + werror = 1; + } + } + } + + if (werror) { + /* + * make sure the error led stay on if there was a previous write + * error, otherwise it gets cleared in avr_write_byte() + */ + pgm->err_led(pgm, ON); + } + } + + return i; +} + + + +/* + * read the AVR device's signature bytes + */ +int avr_signature(PROGRAMMER * pgm, AVRPART * p) +{ + int rc; + + report_progress (0,1,"Reading"); + rc = avr_read(pgm, p, "signature", 0, 0); + if (rc < 0) { + fprintf(stderr, + "%s: error reading signature data for part \"%s\", rc=%d\n", + progname, p->desc, rc); + return -1; + } + report_progress (1,1,NULL); + + return 0; +} + + +/* + * Verify the memory buffer of p with that of v. The byte range of v, + * may be a subset of p. The byte range of p should cover the whole + * chip's memory size. + * + * Return the number of bytes verified, or -1 if they don't match. + */ +int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size) +{ + int i; + unsigned char * buf1, * buf2; + int vsize; + AVRMEM * a, * b; + + a = avr_locate_mem(p, memtype); + if (a == NULL) { + fprintf(stderr, + "avr_verify(): memory type \"%s\" not defined for part %s\n", + memtype, p->desc); + return -1; + } + + b = avr_locate_mem(v, memtype); + if (b == NULL) { + fprintf(stderr, + "avr_verify(): memory type \"%s\" not defined for part %s\n", + memtype, v->desc); + return -1; + } + + buf1 = a->buf; + buf2 = b->buf; + vsize = a->size; + + if (vsize < size) { + fprintf(stderr, + "%s: WARNING: requested verification for %d bytes\n" + "%s%s memory region only contains %d bytes\n" + "%sOnly %d bytes will be verified.\n", + progname, size, + progbuf, memtype, vsize, + progbuf, vsize); + size = vsize; + } + + for (i=0; i0; i--) { + rc = pgm->read_byte(pgm, p, a, a->size-i, &v1); + if (rc < 0) { + fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", + progname, rc); + return -1; + } + cycle_count = (cycle_count << 8) | v1; + } + + /* + * If the EEPROM is erased, the cycle count reads 0xffffffff. + * In this case we return a cycle_count of zero. + * So, the calling function don't have to care about whether or not + * the cycle count was initialized. + */ + if (cycle_count == 0xffffffff) { + cycle_count = 0; + } + + *cycles = (int) cycle_count; + + return 0; +} + + +int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles) +{ + AVRMEM * a; + unsigned char v1; + int rc; + int i; + + a = avr_locate_mem(p, "eeprom"); + if (a == NULL) { + return -1; + } + + for (i=1; i<=4; i++) { + v1 = cycles & 0xff; + cycles = cycles >> 8; + + rc = avr_write_byte(pgm, p, a, a->size-i, v1); + if (rc < 0) { + fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", + progname, rc); + return -1; + } + } + + return 0; + } + +int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + int cycles; + int rc; + + if (do_cycles) { + rc = avr_get_cycle_count(pgm, p, &cycles); + /* + * Don't update the cycle counter, if read failed + */ + if(rc != 0) { + do_cycles = 0; + } + } + + rc = pgm->chip_erase(pgm, p); + + /* + * Don't update the cycle counter, if erase failed + */ + if (do_cycles && (rc == 0)) { + cycles++; + fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n", + progname, cycles); + avr_put_cycle_count(pgm, p, cycles); + } + + return rc; +} + +/* + * Report the progress of a read or write operation from/to the + * device. + * + * The first call of report_progress() should look like this (for a write op): + * + * report_progress (0, 1, "Writing"); + * + * Then hdr should be passed NULL on subsequent calls while the + * operation is progressing. Once the operation is complete, a final + * call should be made as such to ensure proper termination of the + * progress report: + * + * report_progress (1, 1, NULL); + * + * It would be nice if we could reduce the usage to one and only one + * call for each of start, during and end cases. As things stand now, + * that is not possible and makes maintenance a bit more work. + */ +void report_progress (int completed, int total, char *hdr) +{ + static int last = 0; + static double start_time; + int percent = (completed * 100) / total; + struct timeval tv; + double t; + + if (update_progress == NULL) + return; + + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1000000; + + if (hdr) { + last = 0; + start_time = t; + update_progress (percent, t - start_time, hdr); + } + + if (percent > 100) + percent = 100; + + if (percent > last) { + last = percent; + update_progress (percent, t - start_time, hdr); + } + + if (percent == 100) + last = 0; /* Get ready for next time. */ +} diff --git a/avrdude/avr.h b/avrdude/avr.h new file mode 100644 index 00000000..477ab9df --- /dev/null +++ b/avrdude/avr.h @@ -0,0 +1,77 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef __avr_h__ +#define __avr_h__ + +#include + +#include "avrpart.h" +#include "pgm.h" + +typedef void (*FP_UpdateProgress)(int percent, double etime, char *hdr); + +extern struct avrpart parts[]; + +extern FP_UpdateProgress update_progress; + +#ifdef __cplusplus +extern "C" { +#endif + +int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm); +int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value); + +int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose); + +int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr); + +int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data); + +int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data); + +int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose); + +int avr_signature(PROGRAMMER * pgm, AVRPART * p); + +int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size); + +int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles); + +int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles); + +int avr_mem_hiaddr(AVRMEM * mem); + +int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p); + +void report_progress (int completed, int total, char *hdr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/avr910.c b/avrdude/avr910.c new file mode 100644 index 00000000..1bce60fa --- /dev/null +++ b/avrdude/avr910.c @@ -0,0 +1,798 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * Copyright 2007 Joerg Wunsch + * Copyright 2008 Klaus Leidinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel Low Cost Serial programmers which adher to the + * protocol described in application note avr910. + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "config.h" +#include "pgm.h" +#include "avr910.h" +#include "serial.h" + +/* + * Private data for this programmer. + */ +struct pdata +{ + char has_auto_incr_addr; + unsigned char devcode; + unsigned int buffersize; + unsigned char test_blockmode; + unsigned char use_blockmode; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +static void avr910_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: avr910_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); + PDATA(pgm)->test_blockmode = 1; +} + +static void avr910_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + + +static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len) +{ + return serial_send(&pgm->fd, (unsigned char *)buf, len); +} + + +static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len) +{ + int rv; + + rv = serial_recv(&pgm->fd, (unsigned char *)buf, len); + if (rv < 0) { + fprintf(stderr, + "%s: avr910_recv(): programmer is not responding\n", + progname); + exit(1); + } + return 0; +} + + +static int avr910_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(&pgm->fd, display); +} + + +static void avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg) +{ + char c; + + avr910_recv(pgm, &c, 1); + if (c != '\r') { + fprintf(stderr, "%s: error: programmer did not respond to command: %s\n", + progname, errmsg); + exit(1); + } +} + + +/* + * issue the 'chip erase' command to the AVR device + */ +static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + avr910_send(pgm, "e", 1); + avr910_vfy_cmd_sent(pgm, "chip erase"); + + /* + * avr910 firmware may not delay long enough + */ + usleep (p->chip_erase_delay); + + return 0; +} + + +static void avr910_enter_prog_mode(PROGRAMMER * pgm) +{ + avr910_send(pgm, "P", 1); + avr910_vfy_cmd_sent(pgm, "enter prog mode"); +} + + +static void avr910_leave_prog_mode(PROGRAMMER * pgm) +{ + avr910_send(pgm, "L", 1); + avr910_vfy_cmd_sent(pgm, "leave prog mode"); +} + + +/* + * issue the 'program enable' command to the AVR device + */ +static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + return -1; +} + + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + char id[8]; + char sw[2]; + char hw[2]; + char buf[10]; + char type; + char c, devtype_1st; + int dev_supported = 0; + AVRPART * part; + + /* Get the programmer identifier. Programmer returns exactly 7 chars + _without_ the null.*/ + + avr910_send(pgm, "S", 1); + memset (id, 0, sizeof(id)); + avr910_recv(pgm, id, sizeof(id)-1); + + /* Get the HW and SW versions to see if the programmer is present. */ + + avr910_send(pgm, "V", 1); + avr910_recv(pgm, sw, sizeof(sw)); + + avr910_send(pgm, "v", 1); + avr910_recv(pgm, hw, sizeof(hw)); + + /* Get the programmer type (serial or parallel). Expect serial. */ + + avr910_send(pgm, "p", 1); + avr910_recv(pgm, &type, 1); + + fprintf(stderr, "Found programmer: Id = \"%s\"; type = %c\n", id, type); + fprintf(stderr, " Software Version = %c.%c; ", sw[0], sw[1]); + fprintf(stderr, "Hardware Version = %c.%c\n", hw[0], hw[1]); + + /* See if programmer supports autoincrement of address. */ + + avr910_send(pgm, "a", 1); + avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1); + if (PDATA(pgm)->has_auto_incr_addr == 'Y') + fprintf(stderr, "Programmer supports auto addr increment.\n"); + + /* Check support for buffered memory access, ignore if not available */ + + if (PDATA(pgm)->test_blockmode == 1) { + avr910_send(pgm, "b", 1); + avr910_recv(pgm, &c, 1); + if (c == 'Y') { + avr910_recv(pgm, &c, 1); + PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8; + avr910_recv(pgm, &c, 1); + PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c; + fprintf(stderr, + "Programmer supports buffered memory access with " + "buffersize = %u bytes.\n", + PDATA(pgm)->buffersize); + PDATA(pgm)->use_blockmode = 1; + } else { + PDATA(pgm)->use_blockmode = 0; + } + } else { + PDATA(pgm)->use_blockmode = 0; + } + + if (PDATA(pgm)->devcode == 0) { + + /* Get list of devices that the programmer supports. */ + + avr910_send(pgm, "t", 1); + fprintf(stderr, "\nProgrammer supports the following devices:\n"); + devtype_1st = 0; + while (1) { + avr910_recv(pgm, &c, 1); + if (devtype_1st == 0) + devtype_1st = c; + if (c == 0) + break; + part = locate_part_by_avr910_devcode(part_list, c); + + fprintf(stderr, " Device code: 0x%02x = %s\n", c, part ? part->desc : "(unknown)"); + + /* FIXME: Need to lookup devcode and report the device. */ + + if (p->avr910_devcode == c) + dev_supported = 1; + }; + fprintf(stderr,"\n"); + + if (!dev_supported) { + fprintf(stderr, + "%s: %s: selected device is not supported by programmer: %s\n", + progname, ovsigck? "warning": "error", p->id); + if (!ovsigck) + exit(1); + } + /* If the user forced the selection, use the first device + type that is supported by the programmer. */ + buf[1] = ovsigck? devtype_1st: p->avr910_devcode; + } else { + /* devcode overridden by -x devcode= option */ + buf[1] = (char)(PDATA(pgm)->devcode); + } + + /* Tell the programmer which part we selected. */ + buf[0] = 'T'; + /* buf[1] has been set up above */ + + avr910_send(pgm, buf, 2); + avr910_vfy_cmd_sent(pgm, "select device"); + + if (verbose) + fprintf(stderr, + "%s: avr910_devcode selected: 0x%02x\n", + progname, (unsigned)buf[1]); + + avr910_enter_prog_mode(pgm); + + return 0; +} + + +static void avr910_disable(PROGRAMMER * pgm) +{ + /* Do nothing. */ + + return; +} + + +static void avr910_enable(PROGRAMMER * pgm) +{ + /* Do nothing. */ + + return; +} + + +/* + * transmit an AVR device command and return the results; 'cmd' and + * 'res' must point to at least a 4 byte data buffer + */ +static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + char buf[5]; + + /* FIXME: Insert version check here */ + + buf[0] = '.'; /* New Universal Command */ + buf[1] = cmd[0]; + buf[2] = cmd[1]; + buf[3] = cmd[2]; + buf[4] = cmd[3]; + + avr910_send (pgm, buf, 5); + avr910_recv (pgm, buf, 2); + + res[0] = 0x00; /* Dummy value */ + res[1] = cmd[0]; + res[2] = cmd[1]; + res[3] = buf[0]; + + return 0; +} + + +static int avr910_parseextparms(PROGRAMMER * pgm, LISTID extparms) +{ + LNODEID ln; + const char *extended_param; + int rv = 0; + + for (ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if (strncmp(extended_param, "devcode=", strlen("devcode=")) == 0) { + int devcode; + if (sscanf(extended_param, "devcode=%i", &devcode) != 1 || + devcode <= 0 || devcode > 255) { + fprintf(stderr, + "%s: avr910_parseextparms(): invalid devcode '%s'\n", + progname, extended_param); + rv = -1; + continue; + } + if (verbose >= 2) { + fprintf(stderr, + "%s: avr910_parseextparms(): devcode overwritten as 0x%02x\n", + progname, devcode); + } + PDATA(pgm)->devcode = devcode; + + continue; + } + if (strncmp(extended_param, "no_blockmode", strlen("no_blockmode")) == 0) { + if (verbose >= 2) { + fprintf(stderr, + "%s: avr910_parseextparms(-x): no testing for Blockmode\n", + progname); + } + PDATA(pgm)->test_blockmode = 0; + + continue; + } + + fprintf(stderr, + "%s: avr910_parseextparms(): invalid extended parameter '%s'\n", + progname, extended_param); + rv = -1; + } + + return rv; +} + + +static int avr910_open(PROGRAMMER * pgm, char * port) +{ + /* + * If baudrate was not specified use 19.200 Baud + */ + if(pgm->baudrate == 0) { + pgm->baudrate = 19200; + } + + strcpy(pgm->port, port); + if (serial_open(port, pgm->baudrate, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + avr910_drain (pgm, 0); + + return 0; +} + +static void avr910_close(PROGRAMMER * pgm) +{ + avr910_leave_prog_mode(pgm); + + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + + +static void avr910_display(PROGRAMMER * pgm, const char * p) +{ + return; +} + + +static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr) +{ + char cmd[3]; + + cmd[0] = 'A'; + cmd[1] = (addr >> 8) & 0xff; + cmd[2] = addr & 0xff; + + avr910_send(pgm, cmd, sizeof(cmd)); + avr910_vfy_cmd_sent(pgm, "set addr"); +} + + +static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char value) +{ + char cmd[2]; + + if (strcmp(m->desc, "flash") == 0) { + if (addr & 0x01) { + cmd[0] = 'C'; /* Write Program Mem high byte */ + } + else { + cmd[0] = 'c'; + } + + addr >>= 1; + } + else if (strcmp(m->desc, "eeprom") == 0) { + cmd[0] = 'D'; + } + else { + return avr_write_byte_default(pgm, p, m, addr, value); + } + + cmd[1] = value; + + avr910_set_addr(pgm, addr); + + avr910_send(pgm, cmd, sizeof(cmd)); + avr910_vfy_cmd_sent(pgm, "write byte"); + + return 0; +} + + +static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value) +{ + char buf[2]; + + avr910_set_addr(pgm, addr >> 1); + + avr910_send(pgm, "R", 1); + + /* Read back the program mem word (MSB first) */ + avr910_recv(pgm, buf, sizeof(buf)); + + if ((addr & 0x01) == 0) { + *value = buf[1]; + } + else { + *value = buf[0]; + } + + return 0; +} + + +static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value) +{ + avr910_set_addr(pgm, addr); + avr910_send(pgm, "d", 1); + avr910_recv(pgm, (char *)value, 1); + + return 0; +} + + +static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value) +{ + if (strcmp(m->desc, "flash") == 0) { + return avr910_read_byte_flash(pgm, p, m, addr, value); + } + + if (strcmp(m->desc, "eeprom") == 0) { + return avr910_read_byte_eeprom(pgm, p, m, addr, value); + } + + return avr_read_byte_default(pgm, p, m, addr, value); +} + + +static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned char cmd[] = {'c', 'C'}; + char buf[2]; + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + unsigned int page_addr; + int page_bytes = page_size; + int page_wr_cmd_pending = 0; + + page_addr = addr; + avr910_set_addr(pgm, addr>>1); + + while (addr < max_addr) { + page_wr_cmd_pending = 1; + buf[0] = cmd[addr & 0x01]; + buf[1] = m->buf[addr]; + avr910_send(pgm, buf, sizeof(buf)); + avr910_vfy_cmd_sent(pgm, "write byte"); + + addr++; + page_bytes--; + + if (m->paged && (page_bytes == 0)) { + /* Send the "Issue Page Write" if we have sent a whole page. */ + + avr910_set_addr(pgm, page_addr>>1); + avr910_send(pgm, "m", 1); + avr910_vfy_cmd_sent(pgm, "flush page"); + + page_wr_cmd_pending = 0; + usleep(m->max_write_delay); + avr910_set_addr(pgm, addr>>1); + + /* Set page address for next page. */ + + page_addr = addr; + page_bytes = page_size; + } + else if ((PDATA(pgm)->has_auto_incr_addr != 'Y') && ((addr & 0x01) == 0)) { + avr910_set_addr(pgm, addr>>1); + } + + report_progress (addr, max_addr, NULL); + } + + /* If we didn't send the page wr cmd after the last byte written in the + loop, send it now. */ + + if (page_wr_cmd_pending) { + avr910_set_addr(pgm, page_addr>>1); + avr910_send(pgm, "m", 1); + avr910_vfy_cmd_sent(pgm, "flush final page"); + usleep(m->max_write_delay); + } + + return addr; +} + + +static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p, + AVRMEM * m, int page_size, int n_bytes) +{ + char cmd[2]; + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + + avr910_set_addr(pgm, addr); + + cmd[0] = 'D'; + + while (addr < max_addr) { + cmd[1] = m->buf[addr]; + avr910_send(pgm, cmd, sizeof(cmd)); + avr910_vfy_cmd_sent(pgm, "write byte"); + usleep(m->max_write_delay); + + addr++; + + if (PDATA(pgm)->has_auto_incr_addr != 'Y') { + avr910_set_addr(pgm, addr); + } + + report_progress (addr, max_addr, NULL); + } + + return addr; +} + + +static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int rval = 0; + if (PDATA(pgm)->use_blockmode == 0) { + if (strcmp(m->desc, "flash") == 0) { + rval = avr910_paged_write_flash(pgm, p, m, page_size, n_bytes); + } else if (strcmp(m->desc, "eeprom") == 0) { + rval = avr910_paged_write_eeprom(pgm, p, m, page_size, n_bytes); + } else { + rval = -2; + } + } + + if (PDATA(pgm)->use_blockmode == 1) { + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + char *cmd; + unsigned int blocksize = PDATA(pgm)->buffersize; + + if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) + rval = -2; + + if (m->desc[0] == 'e') + blocksize = 1; /* Write to eeprom single bytes only */ + avr910_set_addr(pgm, addr); + + cmd = malloc(4 + blocksize); + if (!cmd) rval = -1; + cmd[0] = 'B'; + cmd[3] = toupper((int)(m->desc[0])); + + while (addr < max_addr) { + if ((max_addr - addr) < blocksize) { + blocksize = max_addr - addr; + }; + memcpy(&cmd[4], &m->buf[addr], blocksize); + cmd[1] = (blocksize >> 8) & 0xff; + cmd[2] = blocksize & 0xff; + + avr910_send(pgm, cmd, 4 + blocksize); + avr910_vfy_cmd_sent(pgm, "write block"); + + addr += blocksize; + + report_progress (addr, max_addr, NULL); + } /* while */ + free(cmd); + + rval = addr; + } + return rval; +} + + +static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + char cmd; + int rd_size = 1; + unsigned int addr = 0; + unsigned int max_addr; + char buf[2]; + int rval=0; + + if (PDATA(pgm)->use_blockmode == 0) { + + if (strcmp(m->desc, "flash") == 0) { + cmd = 'R'; + rd_size = 2; /* read two bytes per addr */ + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd = 'd'; + rd_size = 1; + } else { + rval = -2; + } + + max_addr = n_bytes/rd_size; + + avr910_set_addr(pgm, addr); + + while (addr < max_addr) { + avr910_send(pgm, &cmd, 1); + if (cmd == 'R') { + /* The 'R' command returns two bytes, MSB first, we need to put the data + into the memory buffer LSB first. */ + avr910_recv(pgm, buf, 2); + m->buf[addr*2] = buf[1]; /* LSB */ + m->buf[addr*2+1] = buf[0]; /* MSB */ + } + else { + avr910_recv(pgm, (char *)&m->buf[addr], 1); + } + + addr++; + + if (PDATA(pgm)->has_auto_incr_addr != 'Y') { + avr910_set_addr(pgm, addr); + } + + report_progress (addr, max_addr, NULL); + } + + rval = addr * rd_size; + } + + if (PDATA(pgm)->use_blockmode == 1) { + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + int rd_size = 1; + + /* check parameter syntax: only "flash" or "eeprom" is allowed */ + if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) + rval = -2; + + /* use buffered mode */ + char cmd[4]; + int blocksize = PDATA(pgm)->buffersize; + + cmd[0] = 'g'; + cmd[3] = toupper((int)(m->desc[0])); + + avr910_set_addr(pgm, addr); + + while (addr < max_addr) { + if ((max_addr - addr) < blocksize) { + blocksize = max_addr - addr; + }; + cmd[1] = (blocksize >> 8) & 0xff; + cmd[2] = blocksize & 0xff; + + avr910_send(pgm, cmd, 4); + avr910_recv(pgm, (char *)&m->buf[addr], blocksize); + + addr += blocksize; + + report_progress (addr, max_addr, NULL); + } + + rval = addr * rd_size; + } + + return rval; +} + +/* Signature byte reads are always 3 bytes. */ + +static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) +{ + unsigned char tmp; + + if (m->size < 3) { + fprintf(stderr, "%s: memsize too small for sig byte read", progname); + return -1; + } + + avr910_send(pgm, "s", 1); + avr910_recv(pgm, (char *)m->buf, 3); + /* Returned signature has wrong order. */ + tmp = m->buf[2]; + m->buf[2] = m->buf[0]; + m->buf[0] = tmp; + + return 3; +} + + +void avr910_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "avr910"); + + /* + * mandatory functions + */ + pgm->initialize = avr910_initialize; + pgm->display = avr910_display; + pgm->enable = avr910_enable; + pgm->disable = avr910_disable; + pgm->program_enable = avr910_program_enable; + pgm->chip_erase = avr910_chip_erase; + pgm->cmd = avr910_cmd; + pgm->open = avr910_open; + pgm->close = avr910_close; + + /* + * optional functions + */ + + pgm->write_byte = avr910_write_byte; + pgm->read_byte = avr910_read_byte; + + pgm->paged_write = avr910_paged_write; + pgm->paged_load = avr910_paged_load; + + pgm->read_sig_bytes = avr910_read_sig_bytes; + + pgm->parseextparams = avr910_parseextparms; + pgm->setup = avr910_setup; + pgm->teardown = avr910_teardown; +} diff --git a/avrdude/avr910.h b/avrdude/avr910.h new file mode 100644 index 00000000..ed8b2c56 --- /dev/null +++ b/avrdude/avr910.h @@ -0,0 +1,37 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef avr910_h +#define avr910_h + +#include "avrpart.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void avr910_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif /* avr910_h */ diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1 new file mode 100644 index 00000000..f63f527e --- /dev/null +++ b/avrdude/avrdude.1 @@ -0,0 +1,1086 @@ +.\" +.\" avrdude - A Downloader/Uploader for AVR device programmers +.\" Copyright (C) 2001, 2002, 2003, 2005 - 2011 Joerg Wunsch +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +.\" +.\" +.\" $Id$ +.\" +.Dd DATE August 17, 2011 +.Os +.Dt AVRDUDE 1 +.Sh NAME +.Nm avrdude +.Nd driver program for ``simple'' Atmel AVR MCU programmer +.Sh SYNOPSIS +.Nm +.Fl p Ar partno +.Op Fl b Ar baudrate +.Op Fl B Ar bitclock +.Op Fl c Ar programmer-id +.Op Fl C Ar config-file +.Op Fl D +.Op Fl e +.Oo Fl E Ar exitspec Ns +.Op \&, Ns Ar exitspec +.Oc +.Op Fl F +.Op Fl i Ar delay +.Op Fl n +.Op Fl O +.Op Fl P Ar port +.Op Fl q +.Op Fl s +.Op Fl t +.Op Fl u +.Op Fl U Ar memtype:op:filename:filefmt +.Op Fl v +.Op Fl x Ar extended_param +.Op Fl V +.Op Fl y +.Op Fl Y +.Sh DESCRIPTION +.Nm Avrdude +is a program for downloading code and data to Atmel AVR +microcontrollers. +.Nm Avrdude +supports Atmel's STK500 programmer, +Atmel's AVRISP and AVRISP mkII devices, +Atmel's STK600, +Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode), +programmers complying to AppNote AVR910 and AVR109 (including the Butterfly), +as well as a simple hard-wired +programmer connected directly to a +.Xr ppi 4 +or +.Xr parport 4 +parallel port, or to a standard serial port. +In the simplest case, the hardware consists just of a +cable connecting the respective AVR signal lines to the parallel port. +.Pp +The MCU is programmed in +.Em serial programming mode , +so, for the +.Xr ppi 4 +based programmer, the MCU signals +.Ql /RESET , +.Ql SCK , +.Ql MISO +and +.Ql MOSI +need to be connected to the parallel port. Optionally, some otherwise +unused output pins of the parallel port can be used to supply power +for the MCU part, so it is also possible to construct a passive +stand-alone programming device. Some status LEDs indicating the +current operating state of the programmer can be connected, and a +signal is available to control a buffer/driver IC 74LS367 (or +74HCT367). The latter can be useful to decouple the parallel port +from the MCU when in-system programming is used. +.Pp +A number of equally simple bit-bang programming adapters that connect +to a serial port are supported as well, among them the popular +Ponyprog serial adapter, and the DASA and DASA3 adapters that used to +be supported by uisp(1). +Note that these adapters are meant to be attached to a physical serial +port. +Connecting to a serial port emulated on top of USB is likely to not +work at all, or to work abysmally slow. +.Pp +Atmel's STK500 programmer is also supported and connects to a serial +port. +Both, firmware versions 1.x and 2.x can be handled, but require a +different programmer type specification (by now). +Using firmware version 2, high-voltage programming is also supported, +both parallel and serial +(programmer types stk500pp and stk500hvsp). +.Pp +Wiring boards are supported, utilizing STK500 V2.x protocol, but +a simple DTR/RTS toggle is used to set the boards into programming mode. +The programmer type is ``wiring''. +.Pp +The Arduino (which is very similar to the STK500 1.x) is supported via +its own programmer type specification ``arduino''. +.Pp +The BusPirate is a versatile tool that can also be used as an AVR programmer. +A single BusPirate can be connected to up to 3 independent AVRs. See +the section on +.Em extended parameters +below for details. +.Pp +Atmel's STK600 programmer is supported in ISP and high-voltage +programming modes, and connects through the USB. +For ATxmega devices, the STK600 is supported in PDI mode. +For ATtiny4/5/9/10 devices, the STK600 and AVRISP mkII are supported in TPI mode. +.Pp +The simple serial programmer described in Atmel's application note +AVR910, and the bootloader described in Atmel's application note +AVR109 (which is also used by the AVR Butterfly evaluation board), are +supported on a serial port. +.Pp +Atmel's JTAG ICE (both mkI and mkII) is supported as well to up- or download memory +areas from/to an AVR target (no support for on-chip debugging). +For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported, provided +it has a firmware revision of at least 4.14 (decimal). +See below for the limitations of debugWire. +For ATxmega devices, the JTAG ICE mkII is supported in PDI mode, provided it +has a revision 1 hardware and firmware version of at least 5.37 (decimal). +.Pp +The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire). +When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a +JTAG ICE mkII, so all device-specific comments for that device +will apply as well. +When used in ISP mode, the AVR Dragon behaves similar to an +AVRISP mkII (or JTAG ICE mkII in ISP mode), so all device-specific +comments will apply there. +In particular, the Dragon starts out with a rather fast ISP clock +frequency, so the +.Fl B Ar bitclock +option might be required to achieve a stable ISP communication. +For ATxmega devices, the AVR Dragon is supported in PDI mode, provided it +has a firmware version of at least 6.11 (decimal). +.Pp +The avrftdi, USBasp ISP and USBtinyISP adapters are also supported, provided +.Nm avrdude +has been compiled with libusb support. +USBasp ISP and USBtinyISP both feature simple firmware-only USB implementations, +running on an ATmega8 (or ATmega88), or ATtiny2313, respectively. If libftdi has +has been compiled in +.Nm avrdude , +the avrftdi device adds support for many programmers using FTDI's 2232C/D/H +and 4232H parts running in MPSSE mode, which hard-codes (in the chip) +SCK to bit 1, MOSI to bit 2, and MISO to bit 3. Reset is usually bit 4. +.Pp +Input files can be provided, and output files can be written in +different file formats, such as raw binary files containing the data +to download to the chip, Intel hex format, or Motorola S-record +format. There are a number of tools available to produce those files, +like +.Xr asl 1 +as a standalone assembler, or +.Xr avr-objcopy 1 +for the final stage of the GNU toolchain for the AVR microcontroller. +.Pp +.Nm Avrdude +can program the EEPROM and flash ROM memory cells of supported AVR +parts. Where supported by the serial instruction set, fuse bits and +lock bits can be programmed as well. These are implemented within +.Nm +as separate memory types and can be programmed using data from a file +(see the +.Fl m +option) or from terminal mode (see the +.Ar dump +and +.Ar write +commands). It is also possible to read the chip (provided it has not +been code-protected previously, of course) and store the data in a +file. Finally, a ``terminal'' mode is available that allows one to +interactively communicate with the MCU, and to display or program +individual memory cells. +On the STK500 and STK600 programmer, several operational parameters (target supply +voltage, target Aref voltage, master clock) can be examined and changed +from within terminal mode as well. +.Ss Options +In order to control all the different operation modi, a number of options +need to be specified to +.Nm avrdude . +.Bl -tag -offset indent -width indent +.It Fl p Ar partno +This is the only option that is mandatory for every invocation of +.Nm avrdude . +It specifies the type of the MCU connected to the programmer. These are read from the config file. If +.Nm avrdude +does not know about a part that you have, simply add it to the config +file (be sure and submit a patch back to the author so that it can be +incorporated for the next version). See the sample config file for +the format. Currently, the following MCU types are understood: +.Pp +.TS +ll. +\fBOption tag\fP \fBOfficial part name\fP +1200 AT90S1200 +2313 AT90S2313 +2333 AT90S2333 +2343 AT90S2343 (*) +4414 AT90S4414 +4433 AT90S4433 +4434 AT90S4434 +8515 AT90S8515 +8535 AT90S8535 +c128 AT90CAN128 +c32 AT90CAN32 +c64 AT90CAN64 +m103 ATmega103 +m128 ATmega128 +m1280 ATmega1280 +m1281 ATmega1281 +m1284p ATmega1284P +m128rfa1 ATmega128RFA1 +m16 ATmega16 +m161 ATmega161 +m162 ATmega162 +m163 ATmega163 +m164 ATmega164 +m164p ATmega164P +m168 ATmega168 +m168p ATmega168P +m169 ATmega169 +m16u2 ATmega16U2 +m2560 ATmega2560 (**) +m2561 ATmega2561 (**) +m32 ATmega32 +m324p ATmega324P +m325 ATmega325 +m3250 ATmega3250 +m328p ATmega328P +m329 ATmega329 +m3290 ATmega3290 +m329p ATmega329P +m3290p ATmega3290P +m32u2 ATmega32U2 +m32u4 ATmega32U4 +m48 ATmega48 +m64 ATmega64 +m640 ATmega640 +m644p ATmega644P +m644 ATmega644 +m645 ATmega645 +m6450 ATmega6450 +m649 ATmega649 +m6490 ATmega6490 +m8 ATmega8 +m8515 ATmega8515 +m8535 ATmega8535 +m88 ATmega88 +m88p ATmega88P +m8u2 ATmega8U2 +pwm2 AT90PWM2 +pwm2b AT90PWM2B +pwm3 AT90PWM3 +pwm3b AT90PWM3B +t10 ATtiny10 +t12 ATtiny12 (***) +t13 ATtiny13 +t15 ATtiny15 +t2313 ATtiny2313 +t25 ATtiny25 +t26 ATtiny26 +t261 ATtiny261 +t4 ATtiny4 +t4313 ATtiny4313 +t44 ATtiny44 +t45 ATtiny45 +t461 ATtiny461 +t5 ATtiny5 +t84 ATtiny84 +t85 ATtiny85 +t861 ATtiny861 +t88 ATtiny88 +t9 ATtiny9 +ucr2 AT32uca0512 +usb1286 ATmega1286 +usb1287 ATmega1287 +usb162 ATmega162 +usb646 ATmega647 +usb647 ATmega647 +usb82 ATmega82 +x128a1 ATxmega128A1 +x128a1d ATxmega128A1revD +x128a3 ATxmega128A3 +x128a4 ATxmega128A4 +x16a4 ATxmega16A4 +x192a1 ATxmega192A1 +x192a3 ATxmega192A3 +x256a1 ATxmega256A1 +x256a3 ATxmega256A3 +x256a3b ATxmega256A3B +x32a4 ATxmega32A4 +x64a1 ATxmega64A1 +x64a3 ATxmega64A3 +x64a4 ATxmega64A4 +.TE +.Bl -tag -width "(**) " +.It "(*)" +The AT90S2323 and ATtiny22 use the same algorithm. +.It "(**)" +Flash addressing above 128 KB is not supported by all +programming hardware. Known to work are jtag2, stk500v2, +and bit-bang programmers. +.It "(***)" +The ATtiny11 uses the same algorithm, but can only be +programmed in high-voltage serial mode. +.El +.It Fl b Ar baudrate +Override the RS-232 connection baud rate specified in the respective +programmer's entry of the configuration file. +.It Fl B Ar bitclock +Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only). +The value is a floating-point number in microseconds. +The default value of the JTAG ICE results in about 1 microsecond bit +clock period, suitable for target MCUs running at 4 MHz clock and +above. +Unlike certain parameters in the STK500, the JTAG ICE resets all its +parameters to default values when the programming software signs +off from the ICE, so for MCUs running at lower clock speeds, this +parameter must be specified on the command-line. +You can use the 'default_bitclock' keyword in your +.Pa ${HOME}/.avrduderc +file to assign a default value to keep from having to specify this +option on every invocation. +.It Fl c Ar programmer-id +Use the pin configuration specified by the argument. Pin +configurations are read from the config file (see the +.Fl C +option). New pin configurations can be easily added or modified +through the use of a config file to make +.Nm avrdude +work with different programmers as long as the programmer supports the +Atmel AVR serial program method. You can use the 'default_programmer' +keyword in your +.Pa ${HOME}/.avrduderc +file to assign a default programmer to keep from having to specify +this option on every invocation. +.It Fl C Ar config-file +Use the specified config file to load configuration data. This file +contains all programmer and part definitions that +.Nm avrdude +knows about. If you have a programmer or part that +.Nm avrdude +does not know about, you can add it to the config file (be sure and +submit a patch back to the author so that it can be incorporated for +the next version). See the config file, located at +.Pa ${PREFIX}/etc/avrdude.conf , +which contains a description of the format. +.It Fl D +Disable auto erase for flash. When the +.Fl U +option with flash memory is specified, +.Nm +will perform a chip erase before starting any of the programming +operations, since it generally is a mistake to program the flash +without performing an erase first. This option disables that. +Auto erase is not used for ATxmega devices as these devices can +use page erase before writing each page so no explicit chip erase +is required. +Note however that any page not affected by the current operation +will retain its previous contents. +.It Fl e +Causes a chip erase to be executed. This will reset the contents of the +flash ROM and EEPROM to the value +.Ql 0xff , +and clear all lock bits. +Except for ATxmega devices which can use page erase, +it is basically a prerequisite command before the flash ROM can be +reprogrammed again. The only exception would be if the new +contents would exclusively cause bits to be programmed from the value +.Ql 1 +to +.Ql 0 . +Note that in order to reprogram EERPOM cells, no explicit prior chip +erase is required since the MCU provides an auto-erase cycle in that +case before programming the cell. +.It Xo Fl E Ar exitspec Ns +.Op \&, Ns Ar exitspec +.Xc +By default, +.Nm +leaves the parallel port in the same state at exit as it has been +found at startup. This option modifies the state of the +.Ql /RESET +and +.Ql Vcc +lines the parallel port is left at, according to the +.Ar exitspec +arguments provided, as follows: +.Bl -tag -width noreset +.It Ar reset +The +.Ql /RESET +signal will be left activated at program exit, that is it will be held +.Em low , +in order to keep the MCU in reset state afterwards. Note in particular +that the programming algorithm for the AT90S1200 device mandates that +the +.Ql /RESET +signal is active +.Em before +powering up the MCU, so in case an external power supply is used for this +MCU type, a previous invocation of +.Nm +with this option specified is one of the possible ways to guarantee this +condition. +.It Ar noreset +The +.Ql /RESET +line will be deactivated at program exit, thus allowing the MCU target +program to run while the programming hardware remains connected. +.It Ar vcc +This option will leave those parallel port pins active +.Pq \&i. \&e. Em high +that can be used to supply +.Ql Vcc +power to the MCU. +.It Ar novcc +This option will pull the +.Ql Vcc +pins of the parallel port down at program exit. +.It Ar d_high +This option will leave the 8 data pins on the parallel port active. +.Pq \&i. \&e. Em high +.It Ar d_low +This option will leave the 8 data pins on the parallel port inactive. +.Pq \&i. \&e. Em low +.El +.Pp +Multiple +.Ar exitspec +arguments can be separated with commas. +.It Fl F +Normally, +.Nm +tries to verify that the device signature read from the part is +reasonable before continuing. Since it can happen from time to time +that a device has a broken (erased or overwritten) device signature +but is otherwise operating normally, this options is provided to +override the check. +Also, for programmers like the Atmel STK500 and STK600 which can +adjust parameters local to the programming tool (independent of an +actual connection to a target controller), this option can be used +together with +.Fl t +to continue in terminal mode. +.It Fl i Ar delay +For bitbang-type programmers, delay for approximately +.Ar delay +microseconds between each bit state change. +If the host system is very fast, or the target runs off a slow clock +(like a 32 kHz crystal, or the 128 kHz internal RC oscillator), this +can become necessary to satisfy the requirement that the ISP clock +frequency must not be higher than 1/4 of the CPU clock frequency. +This is implemented as a spin-loop delay to allow even for very +short delays. +On Unix-style operating systems, the spin loop is initially calibrated +against a system timer, so the number of microseconds might be rather +realistic, assuming a constant system load while +.Nm +is running. +On Win32 operating systems, a preconfigured number of cycles per +microsecond is assumed that might be off a bit for very fast or very +slow machines. +.It Fl n +No-write - disables actually writing data to the MCU (useful for debugging +.Nm avrdude +). +.It Fl O +Perform a RC oscillator run-time calibration according to Atmel +application note AVR053. +This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII +hardware. +Note that the result will be stored in the EEPROM cell at address 0. +.It Fl P Ar port +Use +.Ar port +to identify the device to which the programmer is attached. By +default the +.Pa /dev/ppi0 +port is used, but if the programmer type normally connects to the +serial port, the +.Pa /dev/cuaa0 +port is the default. If you need to use a different parallel or +serial port, use this option to specify the alternate port name. +.Pp +On Win32 operating systems, the parallel ports are referred to as lpt1 +through lpt3, referring to the addresses 0x378, 0x278, and 0x3BC, +respectively. If the parallel port can be accessed through a different +address, this address can be specified directly, using the common C +language notation (i. e., hexadecimal values are prefixed by +.Ql 0x +). +.Pp +For the JTAG ICE mkII, if +.Nm +has been configured with libusb support, +.Ar port +can alternatively be specified as +.Pa usb Ns Op \&: Ns Ar serialno . +This will cause +.Nm +to search a JTAG ICE mkII on USB. +If +.Ar serialno +is also specified, it will be matched against the serial number read +from any JTAG ICE mkII found on USB. +The match is done after stripping any existing colons from the given +serial number, and right-to-left, so only the least significant bytes +from the serial number need to be given. +.Pp +As the AVRISP mkII device can only be talked to over USB, the very +same method of specifying the port is required there. +.Pp +For the USB programmer "AVR-Doper" running in HID mode, the port must +be specified as +.Ar avrdoper. +Libusb support is required on Unix but not on Windows. For more +information about AVR-Doper see http://www.obdev.at/avrusb/avrdoper.html. +.Pp +For the USBtinyISP, which is a simplicistic device not implementing +serial numbers, multiple devices can be distinguished by their +location in the USB hierarchy. See the the respective +.Em Troubleshooting +entry in the detailed documentation for examples. +.Pp +For programmers that attach to a serial port using some kind of +higher level protocol (as opposed to bit-bang style programmers), +.Ar port +can be specified as +.Pa net Ns \&: Ns Ar host Ns \&: Ns Ar port . +In this case, instead of trying to open a local device, a TCP +network connection to (TCP) +.Ar port +on +.Ar host +is established. +The remote endpoint is assumed to be a terminal or console server +that connects the network stream to a local serial port where the +actual programmer has been attached to. +The port is assumed to be properly configured, for example using a +transparent 8-bit data connection without parity at 115200 Baud +for a STK500. +.Em This feature is currently not implemented for Win32 systems. +.It Fl q +Disable (or quell) output of the progress bar while reading or writing +to the device. Specify it a second time for even quieter operation. +.It Fl s +Disable safemode prompting. When safemode discovers that one or more +fuse bits have unintentionally changed, it will prompt for +confirmation regarding whether or not it should attempt to recover the +fuse bit(s). Specifying this flag disables the prompt and assumes +that the fuse bit(s) should be recovered without asking for +confirmation first. +.It Fl t +Tells +.Nm +to enter the interactive ``terminal'' mode instead of up- or downloading +files. See below for a detailed description of the terminal mode. +.It Fl u +Disable the safemode fuse bit checks. Safemode is enabled by default +and is intended to prevent unintentional fuse bit changes. When +enabled, safemode will issue a warning if the any fuse bits are found +to be different at program exit than they were when +.Nm +was invoked. Safemode won't alter fuse bits itself, but rather will +prompt for instructions, unless the terminal is non-interactive, in +which case safemode is disabled. See the +.Fl s +option to disable safemode prompting. +.It Xo Fl U Ar memtype Ns +.Ar \&: Ns Ar op Ns +.Ar \&: Ns Ar filename Ns +.Op \&: Ns Ar format +.Xc +Perform a memory operation as indicated. The +.Ar memtype +field specifies the memory type to operate on. +The available memory types are device-dependent, the actual +configuration can be viewed with the +.Cm part +command in terminal mode. +Typically, a device's memory configuration at least contains +the memory types +.Ar flash +and +.Ar eeprom . +All memory types currently known are: +.Bl -tag -width "calibration" -compact +.It calibration +One or more bytes of RC oscillator calibration data. +.It eeprom +The EEPROM of the device. +.It efuse +The extended fuse byte. +.It flash +The flash ROM of the device. +.It fuse +The fuse byte in devices that have only a single fuse byte. +.It hfuse +The high fuse byte. +.It lfuse +The low fuse byte. +.It lock +The lock byte. +.It signature +The three device signature bytes (device ID). +.It fuse Ns Em N +The fuse bytes of ATxmega devices, +.Em N +is an integer number +for each fuse supported by the device. +.It application +The application flash area of ATxmega devices. +.It apptable +The application table flash area of ATxmega devices. +.It boot +The boot flash area of ATxmega devices. +.It prodsig +The production signature (calibration) area of ATxmega devices. +.It usersig +The user signature area of ATxmega devices. +.El +.Pp +The +.Ar op +field specifies what operation to perform: +.Bl -tag -width noreset +.It Ar r +read device memory and write to the specified file +.It Ar w +read data from the specified file and write to the device memory +.It Ar v +read data from both the device and the specified file and perform a verify +.El +.Pp +The +.Ar filename +field indicates the name of the file to read or write. +The +.Ar format +field is optional and contains the format of the file to read or +write. +.Ar Format +can be one of: +.Bl -tag -width sss +.It Ar i +Intel Hex +.It Ar s +Motorola S-record +.It Ar r +raw binary; little-endian byte order, in the case of the flash ROM data +.It Ar m +immediate; actual byte values specified on the command line, separated +by commas or spaces. This is good for programming fuse bytes without +having to create a single-byte file or enter terminal mode. +.It Ar a +auto detect; valid for input only, and only if the input is not +provided at +.Em stdin . +.It Ar d +decimal; this and the following formats are only valid on output. +They generate one line of output for the respective memory section, +forming a comma-separated list of the values. +This can be particularly useful for subsequent processing, like for +fuse bit settings. +.It Ar h +hexadecimal; each value will get the string +.Em 0x +prepended. +.It Ar o +octal; each value will get a +.Em 0 +prepended unless it is less than 8 in which case it gets no prefix. +.It Ar b +binary; each value will get the string +.Em 0b +prepended. +.El +.Pp +The default is to use auto detection for input files, and raw binary +format for output files. +Note that if +.Ar filename +contains a colon, the +.Ar format +field is no longer optional since the filename part following the colon +would otherwise be misinterpreted as +.Ar format . +.Pp +As an abbreviation, the form +.Fl U Ar filename +is equivalent to specifying +.Fl U Em flash:w: Ns Ar filename Ns :a . +This will only work if +.Ar filename +does not have a colon in it. +.It Fl v +Enable verbose output. +.It Fl V +Disable automatic verify check when uploading data. +.It Fl x Ar extended_param +Pass +.Ar extended_param +to the chosen programmer implementation as an extended parameter. +The interpretation of the extended parameter depends on the +programmer itself. +See below for a list of programmers accepting extended parameters. +.It Fl y +Tells +.Nm +to use the last four bytes of the connected parts' EEPROM memory to +track the number of times the device has been erased. When this +option is used and the +.Fl e +flag is specified to generate a chip erase, the previous counter will +be saved before the chip erase, it is then incremented, and written +back after the erase cycle completes. Presumably, the device would +only be erased just before being programmed, and thus, this can be +utilized to give an indication of how many erase-rewrite cycles the +part has undergone. Since the FLASH memory can only endure a finite +number of erase-rewrite cycles, one can use this option to track when +a part is nearing the limit. The typical limit for Atmel AVR FLASH is +1000 cycles. Of course, if the application needs the last four bytes +of EEPROM memory, this option should not be used. +.It Fl Y Ar cycles +Instructs +.Nm +to initialize the erase-rewrite cycle counter residing at the last four +bytes of EEPROM memory to the specified value. If the application +needs the last four bytes of EEPROM memory, this option should not be +used. +.El +.Ss Terminal mode +In this mode, +.Nm +only initializes communication with the MCU, and then awaits user +commands on standard input. Commands and parameters may be +abbreviated to the shortest unambiguous form. Terminal mode provides +a command history using +.Xr readline 3 , +so previously entered command lines can be recalled and edited. The +following commands are currently implemented: +.Bl -tag -offset indent -width indent +.It Ar dump memtype addr nbytes +Read +.Ar nbytes +bytes from the specified memory area, and display them in the usual +hexadecimal and ASCII form. +.It Ar dump +Continue dumping the memory contents for another +.Ar nbytes +where the previous +.Ar dump +command left off. +.It Ar write memtype addr byte1 ... byteN +Manually program the respective memory cells, starting at address +.Ar addr , +using the values +.Ar byte1 +through +.Ar byteN . +This feature is not implemented for bank-addressed memories such as +the flash memory of ATMega devices. +.It Ar erase +Perform a chip erase. +.It Ar send b1 b2 b3 b4 +Send raw instruction codes to the AVR device. If you need access to a +feature of an AVR part that is not directly supported by +.Nm , +this command allows you to use it, even though +.Nm +does not implement the command. When using direct SPI mode, up to 3 bytes +can be omitted. +.It Ar sig +Display the device signature bytes. +.It Ar spi +Enter direct SPI mode. The +.Em pgmled +pin acts as slave select. +.Em Only supported on parallel bitbang programmers. +.It Ar part +Display the current part settings and parameters. Includes chip +specific information including all memory types supported by the +device, read/write timing, etc. +.It Ar pgm +Return to programming mode (from direct SPI mode). +.It Ar vtarg voltage +Set the target's supply voltage to +.Ar voltage +Volts. +.Em Only supported on the STK500 and STK600 programmer. +.It Ar varef Oo Ar channel Oc Ar voltage +Set the adjustable voltage source to +.Ar voltage +Volts. +This voltage is normally used to drive the target's +.Em Aref +input on the STK500. +On the Atmel STK600, two reference voltages are available, which +can be selected by the optional +.Ar channel +argument (either 0 or 1). +.Em Only supported on the STK500 and STK600 programmer. +.It Ar fosc freq Ns Op M Ns \&| Ns k +Set the master oscillator to +.Ar freq +Hz. +An optional trailing letter +.Ar \&M +multiplies by 1E6, a trailing letter +.Ar \&k +by 1E3. +.Em Only supported on the STK500 and STK600 programmer. +.It Ar fosc off +Turn the master oscillator off. +.Em Only supported on the STK500 and STK600 programmer. +.It Ar sck period +.Em STK500 and STK600 programmer only: +Set the SCK clock period to +.Ar period +microseconds. +.Pp +.Em JTAG ICE only: +Set the JTAG ICE bit clock period to +.Ar period +microseconds. +Note that unlike STK500 settings, this setting will be reverted to +its default value (approximately 1 microsecond) when the programming +software signs off from the JTAG ICE. +This parameter can also be used on the JTAG ICE mkII to specify the +ISP clock period when operating the ICE in ISP mode. +.It Ar parms +.Em STK500 and STK600 programmer only: +Display the current voltage and master oscillator parameters. +.Pp +.Em JTAG ICE only: +Display the current target supply voltage and JTAG bit clock rate/period. +.It Ar \&? +.It Ar help +Give a short on-line summary of the available commands. +.It Ar quit +Leave terminal mode and thus +.Nm avrdude . +.El +.Ss Default Parallel port pin connections +(these can be changed, see the +.Fl c +option) +.TS +ll. +\fBPin number\fP \fBFunction\fP +2-5 Vcc (optional power supply to MCU) +7 /RESET (to MCU) +8 SCK (to MCU) +9 MOSI (to MCU) +10 MISO (from MCU) +18-25 GND +.TE +.Ss debugWire limitations +The debugWire protocol is Atmel's proprietary one-wire (plus ground) +protocol to allow an in-circuit emulation of the smaller AVR devices, +using the +.Ql /RESET +line. +DebugWire mode is initiated by activating the +.Ql DWEN +fuse, and then power-cycling the target. +While this mode is mainly intended for debugging/emulation, it +also offers limited programming capabilities. +Effectively, the only memory areas that can be read or programmed +in this mode are flash ROM and EEPROM. +It is also possible to read out the signature. +All other memory areas cannot be accessed. +There is no +.Em chip erase +functionality in debugWire mode; instead, while reprogramming the +flash ROM, each flash ROM page is erased right before updating it. +This is done transparently by the JTAG ICE mkII (or AVR Dragon). +The only way back from debugWire mode is to initiate a special +sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the +debugWire mode will be temporarily disabled, and the target can +be accessed using normal ISP programming. +This sequence is automatically initiated by using the JTAG ICE mkII +or AVR Dragon in ISP mode, when they detect that ISP mode cannot be +entered. +.Ss Programmers accepting extended parameters +.Bl -tag -offset indent -width indent +.It Ar JTAG ICE mkII +.It Ar AVR Dragon +When using the JTAG ICE mkII or AVR Dragon in JTAG mode, the +following extended parameter is accepted: +.Bl -tag -offset indent -width indent +.It Ar jtagchain=UB,UA,BB,BA +Setup the JTAG scan chain for +.Ar UB +units before, +.Ar UA +units after, +.Ar BB +bits before, and +.Ar BA +bits after the target AVR, respectively. +Each AVR unit within the chain shifts by 4 bits. +Other JTAG units might require a different bit shift count. +.El +.It Ar AVR910 +.Bl -tag -offset indent -width indent +.It Ar devcode=VALUE +Override the device code selection by using +.Ar VALUE +as the device code. +The programmer is not queried for the list of supported +device codes, and the specified +.Ar VALUE +is not verified but used directly within the +.Ql T +command sent to the programmer. +.Ar VALUE +can be specified using the conventional number notation of the +C programming language. +.El +.Bl -tag -offset indent -width indent +.It Ar no_blockmode +Disables the default checking for block transfer capability. +Use +.Ar no_blockmode +only if your +.Ar AVR910 +programmer creates errors during initial sequence. +.El +.It Ar buspirate +.Bl -tag -offset indent -width indent +.It Ar reset={cs,aux,aux2} +The default setup assumes the BusPirate's CS output pin connected to +the RESET pin on AVR side. It is however possible to have multiple AVRs +connected to the same BP with MISO, MOSI and SCK lines common for all of them. +In such a case one AVR should have its RESET connected to BusPirate's +.Pa CS +pin, second AVR's RESET connected to BusPirate's +.Pa AUX +pin and if your BusPirate has an +.Pa AUX2 +pin (only available on BusPirate version v1a with firmware 3.0 or newer) +use that to activate RESET on the third AVR. +.Pp +It may be a good idea to decouple the BusPirate and the AVR's SPI buses from +each other using a 3-state bus buffer. For example 74HC125 or 74HC244 are some +good candidates with the latches driven by the appropriate reset pin (cs, +aux or aux2). Otherwise the SPI traffic in one active circuit may interfere +with programming the AVR in the other design. +.It Ar speed=<0..7> +BusPirate to AVR SPI speed: +.Bd -literal +0 .. 30 kHz (default) +1 .. 125 kHz +2 .. 250 kHz +3 .. 1 MHz +4 .. 2 MHz +5 .. 2.6 MHz +6 .. 4 MHz +7 .. 8 MHz +.Ed +.It Ar ascii +Use ASCII mode even when the firmware supports BinMode (binary mode). +BinMode is supported in firmware 2.7 and newer, older FW's either don't +have BinMode or their BinMode is buggy. ASCII mode is slower and makes +the above +.Ar reset= +and +.Ar speed= +parameters unavailable. +.El +.It Ar Wiring +When using the Wiring programmer type, the +following optional extended parameter is accepted: +.Bl -tag -offset indent -width indent +.It Ar snooze=<0..32767> +After performing the port open phase, AVRDUDE will wait/snooze for +.Ar snooze +milliseconds before continuing to the protocol sync phase. +No toggling of DTR/RTS is performed if +.Ar snooze +is greater than 0. +.El +.El +.Sh FILES +.Bl -tag -offset indent -width /dev/ppi0XXX +.It Pa /dev/ppi0 +default device to be used for communication with the programming +hardware +.It Pa ${PREFIX}/etc/avrdude.conf +programmer and parts configuration file +.It Pa ${HOME}/.avrduderc +programmer and parts configuration file (per-user overrides) +.It Pa ~/.inputrc +Initialization file for the +.Xr readline 3 +library +.It Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf +Schematic of programming hardware +.El +.\" .Sh EXAMPLES +.Sh DIAGNOSTICS +.Bd -literal +avrdude: jtagmkII_setparm(): bad response to set parameter command: RSP_FAILED +avrdude: jtagmkII_getsync(): ISP activation failed, trying debugWire +avrdude: Target prepared for ISP, signed off. +avrdude: Please restart avrdude without power-cycling the target. +.Ed +.Pp +If the target AVR has been set up for debugWire mode (i. e. the +.Em DWEN +fuse is programmed), normal ISP connection attempts will fail as +the +.Em /RESET +pin is not available. +When using the JTAG ICE mkII in ISP mode, the message shown indicates +that +.Nm +has guessed this condition, and tried to initiate a debugWire reset +to the target. +When successful, this will leave the target AVR in a state where it +can respond to normal ISP communication again (until the next power +cycle). +Typically, the same command is going to be retried again immediately +afterwards, and will then succeed connecting to the target using +normal ISP communication. +.Sh SEE ALSO +.Xr avr-objcopy 1 , +.Xr ppi 4 , +.Xr readline 3 +.Pp +The AVR microcontroller product description can be found at +.Pp +.Dl "http://www.atmel.com/products/AVR/" +.\" .Sh HISTORY +.Sh AUTHORS +.Nm Avrdude +was written by Brian S. Dean . +.Pp +This man page by +.ie t J\(:org Wunsch. +.el Joerg Wunsch. +.Sh BUGS +Please report bugs via +.Dl "http://savannah.nongnu.org/bugs/?group=avrdude" . +.Pp +The JTAG ICE programmers currently cannot write to the flash ROM +one byte at a time. +For that reason, updating the flash ROM from terminal mode does not +work. +.Pp +Page-mode programming the EEPROM through JTAG (i.e. through an +.Fl U +option) requires a prior chip erase. +This is an inherent feature of the way JTAG EEPROM programming works. +This also applies to the STK500 and STK600 in parallel programming mode. +.Pp +The USBasp and USBtinyISP drivers do not offer any option to distinguish multiple +devices connected simultaneously, so effectively only a single device +is supported. +.Pp +The avrftdi driver allows to select specific devices using any combination of vid,pid +serial number (usbsn) vendor description (usbvendoror part description (usbproduct) +as seen with lsusb or whatever tool used to view USB device information. Multiple +devices can be on the bus at the same time. For the H parts, which have multiple MPSSE +interfaces, the interface can also be selected. It defaults to interface 'A'. diff --git a/avrdude/avrdude.conf.in b/avrdude/avrdude.conf.in new file mode 100644 index 00000000..39e21568 --- /dev/null +++ b/avrdude/avrdude.conf.in @@ -0,0 +1,16921 @@ +# $Id$ -*- text -*- +# +# AVRDUDE Configuration File +# +# This file contains configuration data used by AVRDUDE which describes +# the programming hardware pinouts and also provides part definitions. +# AVRDUDE's "-C" command line option specifies the location of the +# configuration file. The "-c" option names the programmer configuration +# which must match one of the entry's "id" parameter. The "-p" option +# identifies which part AVRDUDE is going to be programming and must match +# one of the parts' "id" parameter. +# +# Possible entry formats are: +# +# programmer +# id = [, [, ] ...] ; # are quoted strings +# desc = ; # quoted string +# type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic | +# stk600 | stk600pp | stk600hvsp | +# avr910 | butterfly | usbasp | +# jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw | +# jtagmkII_avr32 | jtagmkii_pdi | +# dragon_dw | dragon_jtag | dragon_isp | dragon_pp | +# dragon_hvsp | dragon_pdi | arduino | wiring; # programmer type +# baudrate = ; # baudrate for avr910-programmer +# vcc = [, ... ] ; # pin number(s) +# reset = ; # pin number +# sck = ; # pin number +# mosi = ; # pin number +# miso = ; # pin number +# errled = ; # pin number +# rdyled = ; # pin number +# pgmled = ; # pin number +# vfyled = ; # pin number +# usbvid = ; # USB VID (Vendor ID) +# usbpid = ; # USB PID (Product ID) +# usbdev = ; # USB interface or other device info +# usbvendor = ; # USB Vendor Name +# usbproduct = ; # USB Product Name +# usbsn = ; # USB Serial Number +# +# To invert a bit, use = ~ , the spaces are important. +# ; +# +# part +# id = ; # quoted string +# desc = ; # quoted string +# has_jtag = ; # part has JTAG i/f +# has_debugwire = ; # part has debugWire i/f +# has_pdi = ; # part has PDI i/f +# has_tpi = ; # part has TPI i/f +# devicecode = ; # deprecated, use stk500_devcode +# stk500_devcode = ; # numeric +# avr910_devcode = ; # numeric +# signature = ; # signature bytes +# chip_erase_delay = ; # micro-seconds +# reset = dedicated | io; +# retry_pulse = reset | sck; +# pgm_enable = ; +# chip_erase = ; +# chip_erase_delay = ; # chip erase delay (us) +# # STK500 parameters (parallel programming IO lines) +# pagel = ; # pin name in hex, i.e., 0xD7 +# bs2 = ; # pin name in hex, i.e., 0xA0 +# serial = ; # can use serial downloading +# parallel = ; # can use par. programming +# # STK500v2 parameters, to be taken from Atmel's XML files +# timeout = ; +# stabdelay = ; +# cmdexedelay = ; +# synchloops = ; +# bytedelay = ; +# pollvalue = ; +# pollindex = ; +# predelay = ; +# postdelay = ; +# pollmethod = ; +# mode = ; +# delay = ; +# blocksize = ; +# readsize = ; +# hvspcmdexedelay = ; +# # STK500v2 HV programming parameters, from XML +# pp_controlstack = , , ...; # PP only +# hvsp_controlstack = , , ...; # HVSP only +# hventerstabdelay = ; +# progmodedelay = ; # PP only +# latchcycles = ; +# togglevtg = ; +# poweroffdelay = ; +# resetdelayms = ; +# resetdelayus = ; +# hvleavestabdelay = ; +# resetdelay = ; +# synchcycles = ; # HVSP only +# chiperasepulsewidth = ; # PP only +# chiperasepolltimeout = ; +# chiperasetime = ; # HVSP only +# programfusepulsewidth = ; # PP only +# programfusepolltimeout = ; +# programlockpulsewidth = ; # PP only +# programlockpolltimeout = ; +# # JTAG ICE mkII parameters, also from XML files +# allowfullpagebitstream = ; +# enablepageprogramming = ; +# idr = ; # IO addr of IDR (OCD) reg. +# rampz = ; # IO addr of RAMPZ reg. +# spmcr = ; # mem addr of SPMC[S]R reg. +# eecr = ; # mem addr of EECR reg. +# # (only when != 0x3c) +# is_avr32 = ; # AVR32 part +# +# memory +# paged = ; # yes / no +# size = ; # bytes +# page_size = ; # bytes +# num_pages = ; # numeric +# min_write_delay = ; # micro-seconds +# max_write_delay = ; # micro-seconds +# readback_p1 = ; # byte value +# readback_p2 = ; # byte value +# pwroff_after_write = ; # yes / no +# read = ; +# write = ; +# read_lo = ; +# read_hi = ; +# write_lo = ; +# write_hi = ; +# loadpage_lo = ; +# loadpage_hi = ; +# writepage = ; +# ; +# ; +# +# If any of the above parameters are not specified, the default value +# of 0 is used for numerics or the empty string ("") for string +# values. If a required parameter is left empty, AVRDUDE will +# complain. +# +# NOTES: +# * 'devicecode' is the device code used by the STK500 (see codes +# listed below) +# * Not all memory types will implement all instructions. +# * AVR Fuse bits and Lock bits are implemented as a type of memory. +# * Example memory types are: +# "flash", "eeprom", "fuse", "lfuse" (low fuse), "hfuse" (high +# fuse), "signature", "calibration", "lock" +# * The memory type specified on the avrdude command line must match +# one of the memory types defined for the specified chip. +# * The pwroff_after_write flag causes avrdude to attempt to +# power the device off and back on after an unsuccessful write to +# the affected memory area if VCC programmer pins are defined. If +# VCC pins are not defined for the programmer, a message +# indicating that the device needs a power-cycle is printed out. +# This flag was added to work around a problem with the +# at90s4433/2333's; see the at90s4433 errata at: +# +# http://www.atmel.com/atmel/acrobat/doc1280.pdf +# +# INSTRUCTION FORMATS +# +# Instruction formats are specified as a comma seperated list of +# string values containing information (bit specifiers) about each +# of the 32 bits of the instruction. Bit specifiers may be one of +# the following formats: +# +# '1' = the bit is always set on input as well as output +# +# '0' = the bit is always clear on input as well as output +# +# 'x' = the bit is ignored on input and output +# +# 'a' = the bit is an address bit, the bit-number matches this bit +# specifier's position within the current instruction byte +# +# 'aN' = the bit is the Nth address bit, bit-number = N, i.e., a12 +# is address bit 12 on input, a0 is address bit 0. +# +# 'i' = the bit is an input data bit +# +# 'o' = the bit is an output data bit +# +# Each instruction must be composed of 32 bit specifiers. The +# instruction specification closely follows the instruction data +# provided in Atmel's data sheets for their parts. +# +# See below for some examples. +# +# +# The following are STK500 part device codes to use for the +# "devicecode" field of the part. These came from Atmel's software +# section avr061.zip which accompanies the application note +# AVR061 available from: +# +# http://www.atmel.com/atmel/acrobat/doc2525.pdf +# + +#define ATTINY10 0x10 /* the _old_ one that never existed! */ +#define ATTINY11 0x11 +#define ATTINY12 0x12 +#define ATTINY15 0x13 +#define ATTINY13 0x14 + +#define ATTINY22 0x20 +#define ATTINY26 0x21 +#define ATTINY28 0x22 +#define ATTINY2313 0x23 + +#define AT90S1200 0x33 + +#define AT90S2313 0x40 +#define AT90S2323 0x41 +#define AT90S2333 0x42 +#define AT90S2343 0x43 + +#define AT90S4414 0x50 +#define AT90S4433 0x51 +#define AT90S4434 0x52 +#define ATMEGA48 0x59 + +#define AT90S8515 0x60 +#define AT90S8535 0x61 +#define AT90C8534 0x62 +#define ATMEGA8515 0x63 +#define ATMEGA8535 0x64 + +#define ATMEGA8 0x70 +#define ATMEGA88 0x73 +#define ATMEGA168 0x86 + +#define ATMEGA161 0x80 +#define ATMEGA163 0x81 +#define ATMEGA16 0x82 +#define ATMEGA162 0x83 +#define ATMEGA169 0x84 + +#define ATMEGA323 0x90 +#define ATMEGA32 0x91 + +#define ATMEGA64 0xA0 + +#define ATMEGA103 0xB1 +#define ATMEGA128 0xB2 +#define AT90CAN128 0xB3 +#define AT90CAN64 0xB3 +#define AT90CAN32 0xB3 + +#define AT86RF401 0xD0 + +#define AT89START 0xE0 +#define AT89S51 0xE0 +#define AT89S52 0xE1 + +# The following table lists the devices in the original AVR910 +# appnote: +# |Device |Signature | Code | +# +-------+----------+------+ +# |tiny12 | 1E 90 05 | 0x55 | +# |tiny15 | 1E 90 06 | 0x56 | +# | | | | +# | S1200 | 1E 90 01 | 0x13 | +# | | | | +# | S2313 | 1E 91 01 | 0x20 | +# | S2323 | 1E 91 02 | 0x48 | +# | S2333 | 1E 91 05 | 0x34 | +# | S2343 | 1E 91 03 | 0x4C | +# | | | | +# | S4414 | 1E 92 01 | 0x28 | +# | S4433 | 1E 92 03 | 0x30 | +# | S4434 | 1E 92 02 | 0x6C | +# | | | | +# | S8515 | 1E 93 01 | 0x38 | +# | S8535 | 1E 93 03 | 0x68 | +# | | | | +# |mega32 | 1E 95 01 | 0x72 | +# |mega83 | 1E 93 05 | 0x65 | +# |mega103| 1E 97 01 | 0x41 | +# |mega161| 1E 94 01 | 0x60 | +# |mega163| 1E 94 02 | 0x64 | + +# Appnote AVR109 also has a table of AVR910 device codes, which +# lists: +# dev avr910 signature +# ATmega8 0x77 0x1E 0x93 0x07 +# ATmega8515 0x3B 0x1E 0x93 0x06 +# ATmega8535 0x6A 0x1E 0x93 0x08 +# ATmega16 0x75 0x1E 0x94 0x03 +# ATmega162 0x63 0x1E 0x94 0x04 +# ATmega163 0x66 0x1E 0x94 0x02 +# ATmega169 0x79 0x1E 0x94 0x05 +# ATmega32 0x7F 0x1E 0x95 0x02 +# ATmega323 0x73 0x1E 0x95 0x01 +# ATmega64 0x46 0x1E 0x96 0x02 +# ATmega128 0x44 0x1E 0x97 0x02 +# +# These codes refer to "BOOT" device codes which are apparently +# different than standard device codes, for whatever reasons +# (often one above the standard code). + +# There are several extended versions of AVR910 implementations around +# in the Internet. These add the following codes (only devices that +# actually exist are listed): + +# ATmega8515 0x3A +# ATmega128 0x43 +# ATmega64 0x45 +# ATtiny26 0x5E +# ATmega8535 0x69 +# ATmega32 0x72 +# ATmega16 0x74 +# ATmega8 0x76 +# ATmega169 0x78 + +# +# Overall avrdude defaults +# +default_parallel = "@DEFAULT_PAR_PORT@"; +default_serial = "@DEFAULT_SER_PORT@"; +# default_bitclock = 2.5 + + +# +# PROGRAMMER DEFINITIONS +# + +# http://wiring.org.co/ +# Basically STK500v2 protocol, with some glue to trigger the +# bootloader. +programmer + id = "wiring"; + desc = "Wiring"; + type = wiring; +; + +programmer + id = "arduino"; + desc = "Arduino"; + type = arduino; +; +# this will interface with the chips on these programmers: +# +# http://real.kiev.ua/old/avreal/en/adapters +# http://www.amontec.com/jtagkey.shtml, jtagkey-tiny.shtml +# http://www.olimex.com/dev/arm-usb-ocd.html, arm-usb-tiny.html +# http://www.ethernut.de/en/hardware/turtelizer/index.html +# http://elk.informatik.fh-augsburg.de/hhweb/doc/openocd/usbjtag/usbjtag.html +# http://dangerousprototypes.com/docs/FT2232_breakout_board +# http://www.ftdichip.com/Products/Modules/DLPModules.htm,DLP-2232*,DLP-USB1232H +# http://flashrom.org/FT2232SPI_Programmer +# +# The drivers will look for a specific device and use the first one found. +# If you have mulitple devices, then look for unique information (like SN) +# And fill that in here. + +programmer + id = "avrftdi"; + desc = "FT2232D based generic programmer"; + type = avrftdi; + usbvid = 0x0403; + usbpid = 0x6010; + usbvendor = ""; + usbproduct = ""; + usbdev = "A"; + usbsn = ""; +#ISP-signals - lower ACBUS-Nibble (default) + reset = 4; + sck = 1; + mosi = 2; + miso = 3; +#LED SIGNALs - higher ACBUS-Nibble +# errled = 5; +# rdyled = 6; +# pgmled = 7; +# vfyled = 8; +#Buffer Signal - ADBUS - Nibble +# buff = 9; +; +# This is an implementation of the above with a buffer IC (74AC244) and +# 4 LEDs directly attached, active low. The buff and reset pins are +# understood (by avrdude) to be active low, so there's no +# need to invert the bits. +programmer + id = "2232HIO"; + desc = "FT2232H based generic programmer"; + type = avrftdi; + usbvid = 0x0403; +# Note: This PID is reserved for generic H devices and +# should be programmed into the EEPROM +# usbpid = 0x8A48; + usbpid = 0x6010; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; +#ISP-signals + reset = 4; + sck = 1; + mosi = 2; + miso = 3; + buff = 5; +#LED SIGNALs + errled = ~ 12; + rdyled = ~ 15; + pgmled = ~ 14; + vfyled = ~ 13; +; + +programmer + id = "jtagkey"; + desc = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2"; + type = avrftdi; + usbvid = 0x0403; +# Note: This PID is used in all JTAGKey variants + usbpid = 0xCFF8; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; +#ISP-signals => 20 - Pin connector on JTAGKey + reset = 4; # TMS 7 violet + sck = 1; # TCK 9 white + mosi = 2; # TDI 5 green + miso = 3; # TDO 13 orange + buff = 5; +# VTG VREF 1 brown with red tip +# GND GND 20 black +# The colors are on the 20 pin breakout cable +# from Amontec +; + +programmer + id = "avrisp"; + desc = "Atmel AVR ISP"; + type = stk500; +; + +programmer + id = "avrispv2"; + desc = "Atmel AVR ISP V2"; + type = stk500v2; +; + +programmer + id = "avrispmkII"; + desc = "Atmel AVR ISP mkII"; + type = stk500v2; +; + +programmer + id = "avrisp2"; + desc = "Atmel AVR ISP mkII"; + type = stk500v2; +; + +programmer + id = "buspirate"; + desc = "The Bus Pirate"; + type = buspirate; +; + +# This is supposed to be the "default" STK500 entry. +# Attempts to select the correct firmware version +# by probing for it. Better use one of the entries +# below instead. +programmer + id = "stk500"; + desc = "Atmel STK500"; + type = stk500generic; +; + +programmer + id = "stk500v1"; + desc = "Atmel STK500 Version 1.x firmware"; + type = stk500; +; + +programmer + id = "mib510"; + desc = "Crossbow MIB510 programming board"; + type = stk500; +; + +programmer + id = "stk500v2"; + desc = "Atmel STK500 Version 2.x firmware"; + type = stk500v2; +; + +programmer + id = "stk500pp"; + desc = "Atmel STK500 V2 in parallel programming mode"; + type = stk500pp; +; + +programmer + id = "stk500hvsp"; + desc = "Atmel STK500 V2 in high-voltage serial programming mode"; + type = stk500hvsp; +; + +programmer + id = "stk600"; + desc = "Atmel STK600"; + type = stk600; +; + +programmer + id = "stk600pp"; + desc = "Atmel STK600 in parallel programming mode"; + type = stk600pp; +; + +programmer + id = "stk600hvsp"; + desc = "Atmel STK600 in high-voltage serial programming mode"; + type = stk600hvsp; +; + +programmer + id = "avr910"; + desc = "Atmel Low Cost Serial Programmer"; + type = avr910; +; + +programmer + id = "usbasp"; + desc = "USBasp, http://www.fischl.de/usbasp/"; + type = usbasp; +; + +programmer + id = "usbtiny"; + desc = "USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/"; + type = usbtiny; +; + +programmer + id = "butterfly"; + desc = "Atmel Butterfly Development Board"; + type = butterfly; +; + +programmer + id = "avr109"; + desc = "Atmel AppNote AVR109 Boot Loader"; + type = butterfly; +; + +programmer + id = "avr911"; + desc = "Atmel AppNote AVR911 AVROSP"; + type = butterfly; +; + +# suggested in http://forum.mikrokopter.de/topic-post48317.html +programmer + id = "mkbutterfly"; + desc = "Mikrokopter.de Butterfly"; + type = butterfly_mk; +; + +programmer + id = "butterfly_mk"; + desc = "Mikrokopter.de Butterfly"; + type = butterfly_mk; +; + +programmer + id = "jtagmkI"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 115200; # default is 115200 + type = jtagmki; +; + +# easier to type +programmer + id = "jtag1"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 115200; # default is 115200 + type = jtagmki; +; + +# easier to type +programmer + id = "jtag1slow"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 19200; + type = jtagmki; +; + +programmer + id = "jtagmkII"; + desc = "Atmel JTAG ICE mkII"; + baudrate = 19200; # default is 19200 + type = jtagmkii; +; + +# easier to type +programmer + id = "jtag2slow"; + desc = "Atmel JTAG ICE mkII"; + baudrate = 19200; # default is 19200 + type = jtagmkii; +; + +# JTAG ICE mkII @ 115200 Bd +programmer + id = "jtag2fast"; + desc = "Atmel JTAG ICE mkII"; + baudrate = 115200; + type = jtagmkii; +; + +# make the fast one the default, people will love that +programmer + id = "jtag2"; + desc = "Atmel JTAG ICE mkII"; + baudrate = 115200; + type = jtagmkii; +; + +# JTAG ICE mkII in ISP mode +programmer + id = "jtag2isp"; + desc = "Atmel JTAG ICE mkII in ISP mode"; + baudrate = 115200; + type = jtagmkii_isp; +; + +# JTAG ICE mkII in debugWire mode +programmer + id = "jtag2dw"; + desc = "Atmel JTAG ICE mkII in debugWire mode"; + baudrate = 115200; + type = jtagmkii_dw; +; + +# JTAG ICE mkII in AVR32 mode +programmer + id = "jtagmkII_avr32"; + desc = "Atmel JTAG ICE mkII im AVR32 mode"; + baudrate = 115200; + type = jtagmkii_avr32; +; + +# JTAG ICE mkII in AVR32 mode +programmer + id = "jtag2avr32"; + desc = "Atmel JTAG ICE mkII im AVR32 mode"; + baudrate = 115200; + type = jtagmkii_avr32; +; + +# JTAG ICE mkII in PDI mode +programmer + id = "jtag2pdi"; + desc = "Atmel JTAG ICE mkII PDI mode"; + baudrate = 115200; + type = jtagmkii_pdi; +; + +# AVR Dragon in JTAG mode +programmer + id = "dragon_jtag"; + desc = "Atmel AVR Dragon in JTAG mode"; + baudrate = 115200; + type = dragon_jtag; +; + +# AVR Dragon in ISP mode +programmer + id = "dragon_isp"; + desc = "Atmel AVR Dragon in ISP mode"; + baudrate = 115200; + type = dragon_isp; +; + +# AVR Dragon in PP mode +programmer + id = "dragon_pp"; + desc = "Atmel AVR Dragon in PP mode"; + baudrate = 115200; + type = dragon_pp; +; + +# AVR Dragon in HVSP mode +programmer + id = "dragon_hvsp"; + desc = "Atmel AVR Dragon in HVSP mode"; + baudrate = 115200; + type = dragon_hvsp; +; + +# AVR Dragon in debugWire mode +programmer + id = "dragon_dw"; + desc = "Atmel AVR Dragon in debugWire mode"; + baudrate = 115200; + type = dragon_dw; +; + +# AVR Dragon in PDI mode +programmer + id = "dragon_pdi"; + desc = "Atmel AVR Dragon in PDI mode"; + baudrate = 115200; + type = dragon_pdi; +; + +programmer + id = "pavr"; + desc = "Jason Kyle's pAVR Serial Programmer"; + type = avr910; +; + +@HAVE_PARPORT_BEGIN@ Inclusion of the following depends on --enable-parport +# Parallel port programmers. + +programmer + id = "bsd"; + desc = "Brian Dean's Programmer, http://www.bsdhome.com/avrdude/"; + type = par; + vcc = 2, 3, 4, 5; + reset = 7; + sck = 8; + mosi = 9; + miso = 10; +; + +programmer + id = "stk200"; + desc = "STK200"; + type = par; + buff = 4, 5; + sck = 6; + mosi = 7; + reset = 9; + miso = 10; +; + +# The programming dongle used by the popular Ponyprog +# utility. It is almost similar to the STK200 one, +# except that there is a LED indicating that the +# programming is currently in progress. + +programmer + id = "pony-stk200"; + desc = "Pony Prog STK200"; + type = par; + buff = 4, 5; + sck = 6; + mosi = 7; + reset = 9; + miso = 10; + pgmled = 8; +; + +programmer + id = "dt006"; + desc = "Dontronics DT006"; + type = par; + reset = 4; + sck = 5; + mosi = 2; + miso = 11; +; + +programmer + id = "bascom"; + desc = "Bascom SAMPLE programming cable"; + type = par; + reset = 4; + sck = 5; + mosi = 2; + miso = 11; +; + +programmer + id = "alf"; + desc = "Nightshade ALF-PgmAVR, http://nightshade.homeip.net/"; + type = par; + vcc = 2, 3, 4, 5; + buff = 6; + reset = 7; + sck = 8; + mosi = 9; + miso = 10; + errled = 1; + rdyled = 14; + pgmled = 16; + vfyled = 17; +; + +programmer + id = "sp12"; + desc = "Steve Bolt's Programmer"; + type = par; + vcc = 4,5,6,7,8; + reset = 3; + sck = 2; + mosi = 9; + miso = 11; +; + +programmer + id = "picoweb"; + desc = "Picoweb Programming Cable, http://www.picoweb.net/"; + type = par; + reset = 2; + sck = 3; + mosi = 4; + miso = 13; +; + +programmer + id = "abcmini"; + desc = "ABCmini Board, aka Dick Smith HOTCHIP"; + type = par; + reset = 4; + sck = 3; + mosi = 2; + miso = 10; +; + +programmer + id = "futurlec"; + desc = "Futurlec.com programming cable."; + type = par; + reset = 3; + sck = 2; + mosi = 1; + miso = 10; +; + + +# From the contributor of the "xil" jtag cable: +# The "vcc" definition isn't really vcc (the cable gets its power from +# the programming circuit) but is necessary to switch one of the +# buffer lines (trying to add it to the "buff" lines doesn't work in +# avrdude versions before 5.5j). +# With this, TMS connects to RESET, TDI to MOSI, TDO to MISO and TCK +# to SCK (plus vcc/gnd of course) +programmer + id = "xil"; + desc = "Xilinx JTAG cable"; + type = par; + mosi = 2; + sck = 3; + reset = 4; + buff = 5; + miso = 13; + vcc = 6; +; + + +programmer + id = "dapa"; + desc = "Direct AVR Parallel Access cable"; + type = par; + vcc = 3; + reset = 16; + sck = 1; + mosi = 2; + miso = 11; +; + +programmer + id = "atisp"; + desc = "AT-ISP V1.1 programming cable for AVR-SDK1 from micro-research.co.th"; + type = par; + reset = ~6; + sck = ~8; + mosi = ~7; + miso = ~10; +; + +programmer + id = "ere-isp-avr"; + desc = "ERE ISP-AVR "; + type = par; + reset = ~4; + sck = 3; + mosi = 2; + miso = 10; +; + +programmer + id = "blaster"; + desc = "Altera ByteBlaster"; + type = par; + sck = 2; + miso = 11; + reset = 3; + mosi = 8; + buff = 14; +; + +# It is almost same as pony-stk200, except vcc on pin 5 to auto +# disconnect port (download on http://electropol.free.fr) +programmer + id = "frank-stk200"; + desc = "Frank STK200"; + type = par; + vcc = 5; + sck = 6; + mosi = 7; + reset = 9; + miso = 10; + pgmled = 8; +; + +# The AT98ISP Cable is a simple parallel dongle for AT89 family. +# http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2877 +programmer +id = "89isp"; +desc = "Atmel at89isp cable"; +type = par; +reset = 17; +sck = 1; +mosi = 2; +miso = 10; +; + +@HAVE_PARPORT_END@ + +# +# some ultra cheap programmers use bitbanging on the +# serialport. +# +# PC - DB9 - Pins for RS232: +# +# GND 5 -- |O +# | O| <- 9 RI +# DTR 4 <- |O | +# | O| <- 8 CTS +# TXD 3 <- |O | +# | O| -> 7 RTS +# RXD 2 -> |O | +# | O| <- 6 DSR +# DCD 1 -> |O +# +# Using RXD is currently not supported. +# Using RI is not supported under Win32 but is supported under Posix. + +# serial ponyprog design (dasa2 in uisp) +# reset=!txd sck=rts mosi=dtr miso=cts + +programmer + id = "ponyser"; + desc = "design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts"; + type = serbb; + reset = ~3; + sck = 7; + mosi = 4; + miso = 8; +; + +# Same as above, different name +# reset=!txd sck=rts mosi=dtr miso=cts + +programmer + id = "siprog"; + desc = "Lancos SI-Prog "; + type = serbb; + reset = ~3; + sck = 7; + mosi = 4; + miso = 8; +; + +# unknown (dasa in uisp) +# reset=rts sck=dtr mosi=txd miso=cts + +programmer + id = "dasa"; + desc = "serial port banging, reset=rts sck=dtr mosi=txd miso=cts"; + type = serbb; + reset = 7; + sck = 4; + mosi = 3; + miso = 8; +; + +# unknown (dasa3 in uisp) +# reset=!dtr sck=rts mosi=txd miso=cts + +programmer + id = "dasa3"; + desc = "serial port banging, reset=!dtr sck=rts mosi=txd miso=cts"; + type = serbb; + reset = ~4; + sck = 7; + mosi = 3; + miso = 8; +; + +# C2N232i (jumper configuration "auto") +# reset=dtr sck=!rts mosi=!txd miso=!cts + +programmer + id = "c2n232i"; + desc = "serial port banging, reset=dtr sck=!rts mosi=!txd miso=!cts"; + type = serbb; + reset = 4; + sck = ~7; + mosi = ~3; + miso = ~8; +; + +# +# PART DEFINITIONS +# + +#------------------------------------------------------------ +# ATtiny11 +#------------------------------------------------------------ + +# This is an HVSP-only device. + +part + id = "t11"; + desc = "ATtiny11"; + stk500_devcode = 0x11; + signature = 0x1e 0x90 0x04; + chip_erase_delay = 20000; + + timeout = 200; + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + blocksize = 64; + readsize = 256; + delay = 5; + ; + + memory "flash" + size = 1024; + blocksize = 128; + readsize = 256; + delay = 3; + ; + + memory "signature" + size = 3; + ; + + memory "lock" + size = 1; + ; + + memory "calibration" + size = 1; + ; + + memory "fuse" + size = 1; + ; +; + +#------------------------------------------------------------ +# ATtiny12 +#------------------------------------------------------------ + +part + id = "t12"; + desc = "ATtiny12"; + stk500_devcode = 0x12; + avr910_devcode = 0x55; + signature = 0x1e 0x90 0x05; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 8; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + size = 1024; + min_write_delay = 4500; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 5; + blocksize = 128; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "fuse" + size = 1; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; +; + +#------------------------------------------------------------ +# ATtiny13 +#------------------------------------------------------------ + +part + id = "t13"; + desc = "ATtiny13"; + has_debugwire = yes; + flash_instr = 0xB4, 0x0E, 0x1E; + eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x0E, 0xB4, 0x0E, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x14; + signature = 0x1e 0x90 0x07; + chip_erase_delay = 4000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 90; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 5; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 1024; + page_size = 32; + num_pages = 32; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 0 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 0 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 0 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny15 +#------------------------------------------------------------ + +part + id = "t15"; + desc = "ATtiny15"; + stk500_devcode = 0x13; + avr910_devcode = 0x56; + signature = 0x1e 0x90 0x06; + chip_erase_delay = 8200; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 5; + synchcycles = 6; + latchcycles = 16; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + min_write_delay = 8200; + max_write_delay = 8200; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + size = 1024; + min_write_delay = 4100; + max_write_delay = 4100; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 5; + blocksize = 128; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "fuse" + size = 1; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x o o o o x x o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", + "x x x x x x x x i i i i 1 1 i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; +; + +#------------------------------------------------------------ +# AT90s1200 +#------------------------------------------------------------ + +part + id = "1200"; + desc = "AT90S1200"; + stk500_devcode = 0x33; + avr910_devcode = 0x13; + signature = 0x1e 0x90 0x01; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 1; + bytedelay = 0; + pollindex = 0; + pollvalue = 0xFF; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 64; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 32; + readsize = 256; + ; + memory "flash" + size = 1024; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x02; + delay = 15; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + +#------------------------------------------------------------ +# AT90s4414 +#------------------------------------------------------------ + +part + id = "4414"; + desc = "AT90S4414"; + stk500_devcode = 0x50; + avr910_devcode = 0x28; + signature = 0x1e 0x92 0x01; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 256; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "flash" + size = 4096; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x7f; + readback_p2 = 0x7f; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# AT90s2313 +#------------------------------------------------------------ + +part + id = "2313"; + desc = "AT90S2313"; + stk500_devcode = 0x40; + avr910_devcode = 0x20; + signature = 0x1e 0x91 0x01; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 128; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "flash" + size = 2048; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x7f; + readback_p2 = 0x7f; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x i i x", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# AT90s2333 +#------------------------------------------------------------ + +part + id = "2333"; +##### WARNING: No XML file for device 'AT90S2333'! ##### + desc = "AT90S2333"; + stk500_devcode = 0x42; + avr910_devcode = 0x34; + signature = 0x1e 0x91 0x05; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 128; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + size = 2048; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + pwroff_after_write = yes; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + + +#------------------------------------------------------------ +# AT90s2343 (also AT90s2323 and ATtiny22) +#------------------------------------------------------------ + +part + id = "2343"; + desc = "AT90S2343"; + stk500_devcode = 0x43; + avr910_devcode = 0x4c; + signature = 0x1e 0x91 0x03; + chip_erase_delay = 18000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 0; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 128; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "flash" + size = 2048; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 128; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x o o o x x x x o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x o o o x x x x o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + + +#------------------------------------------------------------ +# AT90s4433 +#------------------------------------------------------------ + +part + id = "4433"; + desc = "AT90S4433"; + stk500_devcode = 0x51; + avr910_devcode = 0x30; + signature = 0x1e 0x92 0x03; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 256; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "flash" + size = 4096; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + pwroff_after_write = yes; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + +#------------------------------------------------------------ +# AT90s4434 +#------------------------------------------------------------ + +part + id = "4434"; +##### WARNING: No XML file for device 'AT90S4434'! ##### + desc = "AT90S4434"; + stk500_devcode = 0x52; + avr910_devcode = 0x6c; + signature = 0x1e 0x92 0x02; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + memory "eeprom" + size = 256; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + ; + memory "flash" + size = 4096; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + +#------------------------------------------------------------ +# AT90s8515 +#------------------------------------------------------------ + +part + id = "8515"; + desc = "AT90S8515"; + stk500_devcode = 0x60; + avr910_devcode = 0x38; + signature = 0x1e 0x93 0x01; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 512; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "flash" + size = 8192; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x7f; + readback_p2 = 0x7f; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# AT90s8535 +#------------------------------------------------------------ + +part + id = "8535"; + desc = "AT90S8535"; + stk500_devcode = 0x61; + avr910_devcode = 0x68; + signature = 0x1e 0x93 0x03; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 512; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "flash" + size = 8192; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x x o"; + write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x o o x x x x x x"; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# ATmega103 +#------------------------------------------------------------ + +part + id = "m103"; + desc = "ATMEGA103"; + stk500_devcode = 0xB1; + avr910_devcode = 0x41; + signature = 0x1e 0x97 0x01; + chip_erase_delay = 112000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x8E, 0x9E, 0x2E, 0x3E, 0xAE, 0xBE, + 0x4E, 0x5E, 0xCE, 0xDE, 0x6E, 0x7E, 0xEE, 0xDE, + 0x66, 0x76, 0xE6, 0xF6, 0x6A, 0x7A, 0xEA, 0x7A, + 0x7F, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 10; + + memory "eeprom" + size = 4096; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 22000; + max_write_delay = 56000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x11; + delay = 70; + blocksize = 256; + readsize = 256; + ; + + memory "fuse" + size = 1; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o x o 1 o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 1 i 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega64 +#------------------------------------------------------------ + +part + id = "m64"; + desc = "ATMEGA64"; + has_jtag = yes; + stk500_devcode = 0xA0; + avr910_devcode = 0x45; + signature = 0x1e 0x96 0x02; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x22; + spmcr = 0x68; + allowfullpagebitstream = yes; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + + + +#------------------------------------------------------------ +# ATmega128 +#------------------------------------------------------------ + +part + id = "m128"; + desc = "ATMEGA128"; + has_jtag = yes; + stk500_devcode = 0xB2; + avr910_devcode = 0x43; + signature = 0x1e 0x97 0x02; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x22; + spmcr = 0x68; + rampz = 0x3b; + allowfullpagebitstream = yes; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90CAN128 +#------------------------------------------------------------ + +part + id = "c128"; + desc = "AT90CAN128"; + has_jtag = yes; + stk500_devcode = 0xB3; +# avr910_devcode = 0x43; + signature = 0x1e 0x97 0x81; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + eecr = 0x3f; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90CAN64 +#------------------------------------------------------------ + +part + id = "c64"; + desc = "AT90CAN64"; + has_jtag = yes; + stk500_devcode = 0xB3; +# avr910_devcode = 0x43; + signature = 0x1e 0x96 0x81; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + eecr = 0x3f; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90CAN32 +#------------------------------------------------------------ + +part + id = "c32"; + desc = "AT90CAN32"; + has_jtag = yes; + stk500_devcode = 0xB3; +# avr910_devcode = 0x43; + signature = 0x1e 0x95 0x81; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + eecr = 0x3f; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 256; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega16 +#------------------------------------------------------------ + +part + id = "m16"; + desc = "ATMEGA16"; + has_jtag = yes; + stk500_devcode = 0x82; + avr910_devcode = 0x74; + signature = 0x1e 0x94 0x03; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 100; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = yes; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x04; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "calibration" + size = 4; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega164P +#------------------------------------------------------------ + +# close to ATmega16 + +part + id = "m164p"; + desc = "ATMEGA164P"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x94 0x0a; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega324P +#------------------------------------------------------------ + +# similar to ATmega164P + +part + id = "m324p"; + desc = "ATMEGA324P"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x95 0x08; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega324PA +#------------------------------------------------------------ + +# similar to ATmega324P + +part + id = "m324pa"; + desc = "ATmega324PA"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x95 0x11; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega644 +#------------------------------------------------------------ + +# similar to ATmega164 + +part + id = "m644"; + desc = "ATMEGA644"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x96 0x09; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega644P +#------------------------------------------------------------ + +# similar to ATmega164p + +part + id = "m644p"; + desc = "ATMEGA644P"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x96 0x0a; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + + +#------------------------------------------------------------ +# ATmega1284P +#------------------------------------------------------------ + +# similar to ATmega164p + +part + id = "m1284p"; + desc = "ATMEGA1284P"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x97 0x05; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + + +#------------------------------------------------------------ +# ATmega162 +#------------------------------------------------------------ + +part + id = "m162"; + desc = "ATMEGA162"; + has_jtag = yes; + stk500_devcode = 0x83; + avr910_devcode = 0x63; + signature = 0x1e 0x94 0x04; + chip_erase_delay = 9000; + pagel = 0xd7; + bs2 = 0xa0; + + idr = 0x04; + spmcr = 0x57; + allowfullpagebitstream = yes; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + + ; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; +; + + + +#------------------------------------------------------------ +# ATmega163 +#------------------------------------------------------------ + +part + id = "m163"; + desc = "ATMEGA163"; + stk500_devcode = 0x81; + avr910_devcode = 0x64; + signature = 0x1e 0x94 0x02; + chip_erase_delay = 32000; + pagel = 0xd7; + bs2 = 0xa0; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 30; + programfusepulsewidth = 0; + programfusepolltimeout = 2; + programlockpulsewidth = 0; + programlockpolltimeout = 2; + + + memory "eeprom" + size = 512; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 16000; + max_write_delay = 16000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x11; + delay = 20; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o x x o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i 1 1 i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x 1 o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x 0 x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega169 +#------------------------------------------------------------ + +part + id = "m169"; + desc = "ATMEGA169"; + has_jtag = yes; + stk500_devcode = 0x85; + avr910_devcode = 0x78; + signature = 0x1e 0x94 0x05; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega329 +#------------------------------------------------------------ + +part + id = "m329"; + desc = "ATMEGA329"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x95 0x03; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega329P +#------------------------------------------------------------ +# Identical to ATmega329 except of the signature + +part + id = "m329p"; + desc = "ATMEGA329P"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x95 0x0b; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega3290 +#------------------------------------------------------------ + +# identical to ATmega329 + +part + id = "m3290"; + desc = "ATMEGA3290"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x95 0x04; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a3 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega3290P +#------------------------------------------------------------ + +# identical to ATmega3290 except of the signature + +part + id = "m3290p"; + desc = "ATMEGA3290P"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x95 0x0c; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a3 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega649 +#------------------------------------------------------------ + +part + id = "m649"; + desc = "ATMEGA649"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x96 0x03; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega6490 +#------------------------------------------------------------ + +# identical to ATmega649 + +part + id = "m6490"; + desc = "ATMEGA6490"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x96 0x04; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega32 +#------------------------------------------------------------ + +part + id = "m32"; + desc = "ATMEGA32"; + has_jtag = yes; + stk500_devcode = 0x91; + avr910_devcode = 0x72; + signature = 0x1e 0x95 0x02; + chip_erase_delay = 9000; + pagel = 0xd7; + bs2 = 0xa0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = yes; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x04; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega161 +#------------------------------------------------------------ + +part + id = "m161"; + desc = "ATMEGA161"; + stk500_devcode = 0x80; + avr910_devcode = 0x60; + signature = 0x1e 0x94 0x01; + chip_erase_delay = 28000; + pagel = 0xd7; + bs2 = 0xa0; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 30; + programfusepulsewidth = 0; + programfusepolltimeout = 2; + programlockpulsewidth = 0; + programlockpolltimeout = 2; + + memory "eeprom" + size = 512; + min_write_delay = 3400; + max_write_delay = 3400; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 5; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 14000; + max_write_delay = 14000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 16; + blocksize = 128; + readsize = 256; + ; + + memory "fuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x o x o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", + "x x x x x x x x 1 i 1 i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega8 +#------------------------------------------------------------ + +part + id = "m8"; + desc = "ATMEGA8"; + stk500_devcode = 0x70; + avr910_devcode = 0x76; + signature = 0x1e 0x93 0x07; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 10000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + page_size = 4; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 128; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + + +#------------------------------------------------------------ +# ATmega8515 +#------------------------------------------------------------ + +part + id = "m8515"; + desc = "ATMEGA8515"; + stk500_devcode = 0x63; + avr910_devcode = 0x3A; + signature = 0x1e 0x93 0x06; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 128; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + + + +#------------------------------------------------------------ +# ATmega8535 +#------------------------------------------------------------ + +part + id = "m8535"; + desc = "ATMEGA8535"; + stk500_devcode = 0x64; + avr910_devcode = 0x69; + signature = 0x1e 0x93 0x08; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 128; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATtiny26 +#------------------------------------------------------------ + +part + id = "t26"; + desc = "ATTINY26"; + stk500_devcode = 0x21; + avr910_devcode = 0x5e; + signature = 0x1e 0x91 0x09; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 16; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x x x x i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny261 +#------------------------------------------------------------ +# Close to ATtiny26 + +part + id = "t261"; + desc = "ATTINY261"; + has_debugwire = yes; + flash_instr = 0xB4, 0x00, 0x10; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +# stk500_devcode = 0x21; +# avr910_devcode = 0x5e; + signature = 0x1e 0x91 0x0c; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 4000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + size = 128; + page_size = 4; + num_pages = 32; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x x x o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny461 +#------------------------------------------------------------ +# Close to ATtiny261 + +part + id = "t461"; + desc = "ATTINY461"; + has_debugwire = yes; + flash_instr = 0xB4, 0x00, 0x10; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +# stk500_devcode = 0x21; +# avr910_devcode = 0x5e; + signature = 0x1e 0x92 0x08; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 4000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + size = 256; + page_size = 4; + num_pages = 64; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = " 1 0 1 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x x x o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny861 +#------------------------------------------------------------ +# Close to ATtiny461 + +part + id = "t861"; + desc = "ATTINY861"; + has_debugwire = yes; + flash_instr = 0xB4, 0x00, 0x10; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +# stk500_devcode = 0x21; +# avr910_devcode = 0x5e; + signature = 0x1e 0x93 0x0d; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 4000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + size = 512; + num_pages = 128; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x x x o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATmega48 +#------------------------------------------------------------ + +part + id = "m48"; + desc = "ATMEGA48"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x59; +# avr910_devcode = 0x; + signature = 0x1e 0x92 0x05; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 45000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 256; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x x", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x x x o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega88 +#------------------------------------------------------------ + +part + id = "m88"; + desc = "ATMEGA88"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x73; +# avr910_devcode = 0x; + signature = 0x1e 0x93 0x0a; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 512; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega88P +#------------------------------------------------------------ + +part + id = "m88p"; + desc = "ATMEGA88P"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x73; +# avr910_devcode = 0x; + signature = 0x1e 0x93 0x0f; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 512; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega168 +#------------------------------------------------------------ + +part + id = "m168"; + desc = "ATMEGA168"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x86; + # avr910_devcode = 0x; + signature = 0x1e 0x94 0x06; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 512; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; +; + +#------------------------------------------------------------ +# ATmega168P +#------------------------------------------------------------ + +part + id = "m168p"; + desc = "ATMEGA168P"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x86; + # avr910_devcode = 0x; + signature = 0x1e 0x94 0x0b; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 512; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; +; + +#------------------------------------------------------------ +# ATtiny88 +#------------------------------------------------------------ + +part + id = "t88"; + desc = "attiny88"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x73; +# avr910_devcode = 0x; + signature = 0x1e 0x93 0x11; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 64; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 64; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega328P +#------------------------------------------------------------ + +part + id = "m328p"; + desc = "ATMEGA328P"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x86; + # avr910_devcode = 0x; + signature = 0x1e 0x95 0x0F; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 1024; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x x o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; +; + +#------------------------------------------------------------ +# ATtiny2313 +#------------------------------------------------------------ + +part + id = "t2313"; + desc = "ATtiny2313"; + has_debugwire = yes; + flash_instr = 0xB2, 0x0F, 0x1F; + eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBA, 0x0F, 0xB2, 0x0F, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x23; +## Use the ATtiny26 devcode: + avr910_devcode = 0x5e; + signature = 0x1e 0x91 0x0a; + pagel = 0xD4; + bs2 = 0xD6; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, + 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, + 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, + 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 128; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + +# The information in the data sheet of April/2004 is wrong, this works: + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + +# The information in the data sheet of April/2004 is wrong, this works: + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + +# The information in the data sheet of April/2004 is wrong, this works: + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny2313 has Signature Bytes: 0x1E 0x91 0x0A. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; +# The Tiny2313 has calibration data for both 4 MHz and 8 MHz. +# The information in the data sheet of April/2004 is wrong, this works: + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny4313 +#------------------------------------------------------------ + +part + id = "t4313"; + desc = "ATtiny4313"; + has_debugwire = yes; + flash_instr = 0xB2, 0x0F, 0x1F; + eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBA, 0x0F, 0xB2, 0x0F, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x23; +## Use the ATtiny26 devcode: + avr910_devcode = 0x5e; + signature = 0x1e 0x92 0x0d; + pagel = 0xD4; + bs2 = 0xD6; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, + 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, + 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, + 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 256; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny4313 has Signature Bytes: 0x1E 0x92 0x0D. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90PWM2 +#------------------------------------------------------------ + +part + id = "pwm2"; + desc = "AT90PWM2"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x65; +## avr910_devcode = ?; + signature = 0x1e 0x93 0x81; + pagel = 0xD8; + bs2 = 0xE2; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; +# AT90PWM2 has Signature Bytes: 0x1E 0x93 0x81. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90PWM3 +#------------------------------------------------------------ + +# Completely identical to AT90PWM2 (including the signature!) + +part + id = "pwm3"; + desc = "AT90PWM3"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x65; +## avr910_devcode = ?; + signature = 0x1e 0x93 0x81; + pagel = 0xD8; + bs2 = 0xE2; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; +# AT90PWM2 has Signature Bytes: 0x1E 0x93 0x81. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90PWM2B +#------------------------------------------------------------ +# Same as AT90PWM2 but different signature. + +part + id = "pwm2b"; + desc = "AT90PWM2B"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x65; +## avr910_devcode = ?; + signature = 0x1e 0x93 0x83; + pagel = 0xD8; + bs2 = 0xE2; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90PWM3B +#------------------------------------------------------------ + +# Completely identical to AT90PWM2B (including the signature!) + +part + id = "pwm3b"; + desc = "AT90PWM3B"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x65; +## avr910_devcode = ?; + signature = 0x1e 0x93 0x83; + pagel = 0xD8; + bs2 = 0xE2; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny25 +#------------------------------------------------------------ + +part + id = "t25"; + desc = "ATtiny25"; + has_debugwire = yes; + flash_instr = 0xB4, 0x02, 0x12; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x91 0x08; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 128; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny25 has Signature Bytes: 0x1E 0x91 0x08. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny45 +#------------------------------------------------------------ + +part + id = "t45"; + desc = "ATtiny45"; + has_debugwire = yes; + flash_instr = 0xB4, 0x02, 0x12; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x92 0x06; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 256; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny45 has Signature Bytes: 0x1E 0x92 0x08. (Data sheet 2586C-AVR-06/05 (doc2586.pdf) indicates otherwise!) + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny85 +#------------------------------------------------------------ + +part + id = "t85"; + desc = "ATtiny85"; + has_debugwire = yes; + flash_instr = 0xB4, 0x02, 0x12; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x93 0x0b; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny85 has Signature Bytes: 0x1E 0x93 0x08. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega640 +#------------------------------------------------------------ +# Almost same as ATmega1280, except for different memory sizes + +part + id = "m640"; + desc = "ATMEGA640"; + signature = 0x1e 0x96 0x08; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega1280 +#------------------------------------------------------------ + +part + id = "m1280"; + desc = "ATMEGA1280"; + signature = 0x1e 0x97 0x03; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega1281 +#------------------------------------------------------------ +# Identical to ATmega1280 + +part + id = "m1281"; + desc = "ATMEGA1281"; + signature = 0x1e 0x97 0x04; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega2560 +#------------------------------------------------------------ + +part + id = "m2560"; + desc = "ATMEGA2560"; + signature = 0x1e 0x98 0x01; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 262144; + page_size = 256; + num_pages = 1024; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega2561 +#------------------------------------------------------------ + +part + id = "m2561"; + desc = "ATMEGA2561"; + signature = 0x1e 0x98 0x02; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 262144; + page_size = 256; + num_pages = 1024; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega128RFA1 +#------------------------------------------------------------ +# Identical to ATmega2561 but half the ROM + +part + id = "m128rfa1"; + desc = "ATMEGA128RFA1"; + signature = 0x1e 0xa7 0x01; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 55000; + pagel = 0xD7; + bs2 = 0xE2; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 50000; + max_write_delay = 50000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 50000; + max_write_delay = 50000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny24 +#------------------------------------------------------------ + +part + id = "t24"; + desc = "ATtiny24"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x91 0x0b; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 70; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 128; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny24 has Signature Bytes: 0x1E 0x91 0x0B. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x x x x x x x i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny44 +#------------------------------------------------------------ + +part + id = "t44"; + desc = "ATtiny44"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x92 0x07; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 70; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 256; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny44 has Signature Bytes: 0x1E 0x92 0x07. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x x x x x x x i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny84 +#------------------------------------------------------------ + +part + id = "t84"; + desc = "ATtiny84"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x93 0x0c; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 70; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny84 has Signature Bytes: 0x1E 0x93 0x0C. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x x x x x x x i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega32u4 +#------------------------------------------------------------ + +part + id = "m32u4"; + desc = "ATmega32U4"; + signature = 0x1e 0x95 0x87; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB646 +#------------------------------------------------------------ + +part + id = "usb646"; + desc = "AT90USB646"; + signature = 0x1e 0x96 0x82; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB647 +#------------------------------------------------------------ +# identical to AT90USB646 + +part + id = "usb647"; + desc = "AT90USB647"; + signature = 0x1e 0x96 0x82; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB1286 +#------------------------------------------------------------ + +part + id = "usb1286"; + desc = "AT90USB1286"; + signature = 0x1e 0x97 0x82; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB1287 +#------------------------------------------------------------ +# identical to AT90USB1286 + +part + id = "usb1287"; + desc = "AT90USB1287"; + signature = 0x1e 0x97 0x82; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# AT90USB162 +#------------------------------------------------------------ + +part + id = "usb162"; + desc = "AT90USB162"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x94 0x82; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB82 +#------------------------------------------------------------ +# Changes against AT90USB162 (beside IDs) +# memory "flash" +# size = 8192; +# num_pages = 64; + +part + id = "usb82"; + desc = "AT90USB82"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x93 0x82; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 8192; + page_size = 128; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega32U2 +#------------------------------------------------------------ +# Changes against AT90USB162 (beside IDs) +# memory "flash" +# size = 32768; +# num_pages = 256; +# memory "eeprom" +# size = 1024; +# num_pages = 256; +part + id = "m32u2"; + desc = "ATmega32U2"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x95 0x8a; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + num_pages = 256; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; +#------------------------------------------------------------ +# ATmega16U2 +#------------------------------------------------------------ +# Changes against ATmega32U2 (beside IDs) +# memory "flash" +# size = 16384; +# num_pages = 128; +# memory "eeprom" +# size = 512; +# num_pages = 128; +part + id = "m16u2"; + desc = "ATmega16U2"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x94 0x89; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega8U2 +#------------------------------------------------------------ +# Changes against ATmega16U2 (beside IDs) +# memory "flash" +# size = 8192; +# page_size = 64; +# blocksize = 64; + +part + id = "m8u2"; + desc = "ATmega8U2"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x93 0x89; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; +#------------------------------------------------------------ +# ATmega325 +#------------------------------------------------------------ + +part + id = "m325"; + desc = "ATMEGA325"; + signature = 0x1e 0x95 0x05; + has_jtag = yes; +# stk500_devcode = 0x??; # No STK500v1 support? +# avr910_devcode = 0x??; # Try the ATmega16 one + avr910_devcode = 0x74; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega645 +#------------------------------------------------------------ + +part + id = "m645"; + desc = "ATMEGA645"; + signature = 0x1E 0x96 0x05; + has_jtag = yes; +# stk500_devcode = 0x??; # No STK500v1 support? +# avr910_devcode = 0x??; # Try the ATmega16 one + avr910_devcode = 0x74; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " 0 0 0 0 0 0 0 0"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega3250 +#------------------------------------------------------------ + +part + id = "m3250"; + desc = "ATMEGA3250"; + signature = 0x1E 0x95 0x06; + has_jtag = yes; +# stk500_devcode = 0x??; # No STK500v1 support? +# avr910_devcode = 0x??; # Try the ATmega16 one + avr910_devcode = 0x74; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega6450 +#------------------------------------------------------------ + +part + id = "m6450"; + desc = "ATMEGA6450"; + signature = 0x1E 0x96 0x06; + has_jtag = yes; +# stk500_devcode = 0x??; # No STK500v1 support? +# avr910_devcode = 0x??; # Try the ATmega16 one + avr910_devcode = 0x74; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " 0 0 0 0 0 0 0 0"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATXMEGA64A1 +#------------------------------------------------------------ + +part + id = "x64a1"; + desc = "ATXMEGA64A1"; + signature = 0x1e 0x96 0x4e; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00010000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00001000; + offset = 0x0080f000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00001000; + offset = 0x00810000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00011000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA128A1 +#------------------------------------------------------------ + +part + id = "x128a1"; + desc = "ATXMEGA128A1"; + signature = 0x1e 0x97 0x4c; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00020000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0081e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00820000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00022000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA128A1REVD +#------------------------------------------------------------ + +part + id = "x128a1d"; + desc = "ATXMEGA128A1REVD"; + signature = 0x1e 0x97 0x41; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00020000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0081e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00820000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00022000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA192A1 +#------------------------------------------------------------ + +part + id = "x192a1"; + desc = "ATXMEGA192A1"; + signature = 0x1e 0x97 0x4e; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00030000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0082e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00830000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00032000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA256A1 +#------------------------------------------------------------ + +part + id = "x256a1"; + desc = "ATXMEGA256A1"; + signature = 0x1e 0x98 0x46; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x1000; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00040000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0083e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00840000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00042000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA64A3 +#------------------------------------------------------------ + +part + id = "x64a3"; + desc = "ATXMEGA64A3"; + signature = 0x1e 0x96 0x42; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00010000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00001000; + offset = 0x0080f000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00001000; + offset = 0x00810000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00011000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA128A3 +#------------------------------------------------------------ + +part + id = "x128a3"; + desc = "ATXMEGA128A3"; + signature = 0x1e 0x97 0x42; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00020000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0081e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00820000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00022000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA192A3 +#------------------------------------------------------------ + +part + id = "x192a3"; + desc = "ATXMEGA192A3"; + signature = 0x1e 0x97 0x44; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00030000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0082e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00830000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00032000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA256A3 +#------------------------------------------------------------ + +part + id = "x256a3"; + desc = "ATXMEGA256A3"; + signature = 0x1e 0x98 0x42; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x1000; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00040000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0083e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00840000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00042000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA256A3B +#------------------------------------------------------------ + +part + id = "x256a3b"; + desc = "ATXMEGA256A3B"; + signature = 0x1e 0x98 0x43; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x1000; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00040000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0083e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00840000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00042000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA16A4 +#------------------------------------------------------------ + +part + id = "x16a4"; + desc = "ATXMEGA16A4"; + signature = 0x1e 0x94 0x41; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0400; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00004000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00001000; + offset = 0x00803000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00001000; + offset = 0x00804000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00005000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA32A4 +#------------------------------------------------------------ + +part + id = "x32a4"; + desc = "ATXMEGA32A4"; + signature = 0x1e 0x95 0x41; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0400; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00008000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00001000; + offset = 0x00807000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00001000; + offset = 0x00808000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00009000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA64A4 +#------------------------------------------------------------ + +part + id = "x64a4"; + desc = "ATXMEGA64A4"; + signature = 0x1e 0x96 0x46; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00010000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00001000; + offset = 0x0080f000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00001000; + offset = 0x00810000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00011000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + +#------------------------------------------------------------ +# ATXMEGA128A4 +#------------------------------------------------------------ + +part + id = "x128a4"; + desc = "ATXMEGA128A4"; + signature = 0x1e 0x97 0x46; + has_jtag = yes; + has_pdi = yes; + nvm_base = 0x01c0; + + memory "eeprom" + size = 0x0800; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x00020000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x00002000; + offset = 0x0081e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x00002000; + offset = 0x00820000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x00022000; + offset = 0x0800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x200; + offset = 0x8e0200; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "signature" + size = 3; + offset = 0x1000090; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; +; + + +#------------------------------------------------------------ +# AVR32UC3A0512 +#------------------------------------------------------------ + +part + id = "ucr2"; + desc = "32UC3A0512"; + signature = 0xED 0xC0 0x3F; + has_jtag = yes; + is_avr32 = yes; + + memory "flash" + paged = yes; + page_size = 512; # bytes + readsize = 512; # bytes + num_pages = 1024; # could be set dynamicly + size = 0x00080000; # could be set dynamicly + offset = 0x80000000; + ; +; + +#------------------------------------------------------------ +# ATtiny4 +#------------------------------------------------------------ + +part + id = "t4"; + desc = "ATtiny4"; + signature = 0x1e 0x8f 0x0a; + has_tpi = yes; + + memory "flash" + size = 512; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; + + memory "signature" + size = 3; + offset = 0x3fc0; + page_size = 16; + ; + + memory "fuse" + size = 1; + offset = 0x3f40; + page_size = 16; + blocksize = 4; + ; + + memory "calibration" + size = 1; + offset = 0x3f80; + page_size = 16; + ; + + memory "lockbits" + size = 1; + offset = 0x3f00; + page_size = 16; + ; +; + + +#------------------------------------------------------------ +# ATtiny5 +#------------------------------------------------------------ + +part + id = "t5"; + desc = "ATtiny5"; + signature = 0x1e 0x8f 0x09; + has_tpi = yes; + + memory "flash" + size = 512; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; + + memory "signature" + size = 3; + offset = 0x3fc0; + page_size = 16; + ; + + memory "fuse" + size = 1; + offset = 0x3f40; + page_size = 16; + blocksize = 4; + ; + + memory "calibration" + size = 1; + offset = 0x3f80; + page_size = 16; + ; + + memory "lockbits" + size = 1; + offset = 0x3f00; + page_size = 16; + ; +; + + +#------------------------------------------------------------ +# ATtiny9 +#------------------------------------------------------------ + +part + id = "t9"; + desc = "ATtiny9"; + signature = 0x1e 0x90 0x08; + has_tpi = yes; + + memory "flash" + size = 1024; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; + + memory "signature" + size = 3; + offset = 0x3fc0; + page_size = 16; + ; + + memory "fuse" + size = 1; + offset = 0x3f40; + page_size = 16; + blocksize = 4; + ; + + memory "calibration" + size = 1; + offset = 0x3f80; + page_size = 16; + ; + + memory "lockbits" + size = 1; + offset = 0x3f00; + page_size = 16; + ; +; + + +#------------------------------------------------------------ +# ATtiny10 +#------------------------------------------------------------ + +part + id = "t10"; + desc = "ATtiny10"; + signature = 0x1e 0x90 0x03; + has_tpi = yes; + + memory "flash" + size = 1024; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; + + memory "signature" + size = 3; + offset = 0x3fc0; + page_size = 16; + ; + + memory "fuse" + size = 1; + offset = 0x3f40; + page_size = 16; + blocksize = 4; + ; + + memory "calibration" + size = 1; + offset = 0x3f80; + page_size = 16; + ; + + memory "lockbits" + size = 1; + offset = 0x3f00; + page_size = 16; + ; +; + + diff --git a/avrdude/avrdude.h b/avrdude/avrdude.h new file mode 100644 index 00000000..0ef19cac --- /dev/null +++ b/avrdude/avrdude.h @@ -0,0 +1,56 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef avrdude_h +#define avrdude_h + +extern char * progname; /* name of program, for messages */ +extern char progbuf[]; /* spaces same length as progname */ + +extern int do_cycles; /* track erase-rewrite cycles (-y) */ +extern int ovsigck; /* override signature check (-F) */ +extern int verbose; /* verbosity level (-v, -vv, ...) */ +extern int quell_progress; /* quiteness level (-q, -qq) */ + +#if defined(WIN32NATIVE) + +#include "ac_cfg.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(HAVE_USLEEP) +int usleep(unsigned int us); +#endif + +#if !defined(HAVE_GETTIMEOFDAY) +struct timezone; +int gettimeofday(struct timeval *tv, struct timezone *tz); +#ifdef __cplusplus +} +#endif +#endif /* HAVE_GETTIMEOFDAY */ + +#endif /* defined(WIN32NATIVE) */ + +#endif diff --git a/avrdude/avrdude.spec.in b/avrdude/avrdude.spec.in new file mode 100644 index 00000000..ff9879f6 --- /dev/null +++ b/avrdude/avrdude.spec.in @@ -0,0 +1,113 @@ +## -*- mode: rpm-spec; -*- +## +## $Id$ +## +## @configure_input@ +## + +%define debug_package %{nil} + +%define _with_docs 1 +%{?_without_docs: %define _with_docs 0} + +Summary: AVRDUDE is software for programming Atmel AVR Microcontrollers. +Name: avrdude +Version: @VERSION@ +Release: 1 +URL: http://savannah.nongnu.org/projects/avrdude +Source0: %{name}-%{version}.tar.gz +License: GPL +Group: Development/Tools +BuildRoot: %{_tmppath}/%{name}-%{version}-root + +%description +AVRDUDE is software for programming Atmel AVR Microcontrollers. + +%if %{_with_docs} +## The avrdude-docs subpackage +%package docs +Summary: Documentation for AVRDUDE. +Group: Documentation +%description docs +Documentation for avrdude in info, html, postscript and pdf formats. +%endif + +%prep +%setup -q + +%build + +./configure --prefix=%{_prefix} --sysconfdir=/etc --mandir=%{_mandir} \ + --infodir=%{_infodir} \ +%if %{_with_docs} + --enable-doc=yes +%else + --enable-doc=no +%endif + +make + +%install +rm -rf $RPM_BUILD_ROOT +make prefix=$RPM_BUILD_ROOT%{_prefix} \ + sysconfdir=$RPM_BUILD_ROOT/etc \ + mandir=$RPM_BUILD_ROOT%{_mandir} \ + infodir=$RPM_BUILD_ROOT%{_infodir} \ + install + +rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/%{name}-%{version} +rm -f $RPM_BUILD_ROOT%{_infodir}/dir + +%clean +rm -rf $RPM_BUILD_ROOT + +%if %{_with_docs} +%post docs +[ -f %{_infodir}/avrdude.info ] && \ + /sbin/install-info %{_infodir}/avrdude.info %{_infodir}/dir || : +[ -f %{_infodir}/avrdude.info.gz ] && \ + /sbin/install-info %{_infodir}/avrdude.info.gz %{_infodir}/dir || : + +%preun docs +if [ $1 = 0 ]; then + [ -f %{_infodir}/avrdude.info ] && \ + /sbin/install-info --delete %{_infodir}/avrdude.info %{_infodir}/dir || : + [ -f %{_infodir}/avrdude.info.gz ] && \ + /sbin/install-info --delete %{_infodir}/avrdude.info.gz %{_infodir}/dir || : +fi +%endif + +%files +%defattr(-,root,root) +%{_prefix}/bin/avrdude +%{_mandir}/man1/avrdude.1.gz +%attr(0644,root,root) %config /etc/avrdude.conf + +%if %{_with_docs} +%files docs +%doc %{_infodir}/*info* +%doc doc/avrdude-html/*.html +%doc doc/TODO +%doc doc/avrdude.ps +%doc doc/avrdude.pdf +%endif + +%changelog +* Fri Sep 23 2005 Galen Seitz +- Default to enable-doc=yes during configure. +- Move info file to docs package. +- Make building of docs package conditional. Basic idea copied from avr-gcc. + +* Wed Aug 27 2003 Theodore A. Roth + [Thanks to Artur Lipowski ] +- Do not build debug package. +- Remove files not packaged to quell RH9 rpmbuild complaints. + +* Wed Mar 05 2003 Theodore A. Roth +- Add docs sub-package. +- Add %post and %preun scriptlets for handling info files. + +* Wed Feb 26 2003 Theodore A. Roth +- Initial build. + + diff --git a/avrdude/avrftdi.c b/avrdude/avrftdi.c new file mode 100644 index 00000000..37d883b6 --- /dev/null +++ b/avrdude/avrftdi.c @@ -0,0 +1,1079 @@ +/* + * avrftdi - extension for avrdude, Wolfgang Moser, Ville Voipio + * Copyright (C) 2011 Hannes Weisbach, Doug Springer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ +/* + * Interface to the MPSSE Engine of FTDI Chips using libftdi. + */ +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "avrftdi.h" + +#ifdef HAVE_LIBUSB +#ifdef HAVE_LIBFTDI + +#include +#include + +/* This is for running the code without having a FTDI-device. + * The generated code is useless! For debugging purposes only. + * This should never be defined, unless you know what you are + * doing. + * If you think you know what you are doing: YOU DONT! + */ +//#define DRYRUN + +static struct ftdi_context ftdic; +static uint16_t pin_value, pin_direction, pin_inversion, led_mask; +static int type; /**type is bcdDevice. C/D is 0x500 H is 0x700 4H is 0x800*/ +static int ftype; /** is from FTDI. Use TYPE_2232C, TYPE_2232H, or TYPE_4232H*/ + +static void buf_dump(unsigned char *buf, int len, char *desc, + int offset, int width) +{ + int i; + fprintf(stderr, "%s begin:\n", desc); + for (i = 0; i < offset; i++) + fprintf(stderr, "%02x ", buf[i]); + fprintf(stderr, "\n"); + for (i++; i <= len; i++) { + fprintf(stderr, "%02x ", buf[i-1]); + if((i-offset) != 0 && (i-offset)%width == 0) + fprintf(stderr, "\n"); + } + fprintf(stderr, "%s end\n", desc); +} + +static int set_frequency(uint32_t freq) +{ + uint32_t divisor; + uint8_t buf[3]; + + /* divisor on 6000000 / freq - 1 */ + divisor = (6000000 / freq) - 1; + if (divisor < 0) { + fprintf(stderr, + "%s failure: Frequency too high (%u > 6 MHz)\n", + progname, freq); + fprintf(stderr, + "resetting Frequency to 6MHz\n"); + divisor = 0; + } + + if (divisor > 65535) { + fprintf(stderr, + "%s failure: Frequency too low (%u < 91.553 Hz)\n", + progname, freq); + fprintf(stderr, + "resetting Frequency to 91.553Hz\n"); + divisor = 65535; + } + + if(verbose) + fprintf(stderr, + "%s info: clock divisor: 0x%04x\n", + progname, divisor); + + buf[0] = 0x86; + buf[1] = (uint8_t)(divisor & 0xff); + buf[2] = (uint8_t)((divisor >> 8) & 0xff); + +#ifndef DRYRUN + E(ftdi_write_data(&ftdic, buf, 3) < 0); +#endif + + return 0; +} + +/* Add a single pin (by pin number) to the pin masks (or to pins), + * update pinmask[pinfunc] */ +static int add_pin(PROGRAMMER *pgm, int pinfunc) +{ + int pin, inversion_mask, mlim; + + pin = pgm->pinno[pinfunc]; + if (verbose) + fprintf(stderr, + "add_pin: %d: bit 0x%04x inv=0x%04x\n", + pinfunc, pin, + (pin & PIN_INVERSE)? (1<< ((pin&PIN_MASK) - 1)): 0); + + /* non-existent definitions, go away */ + if (pin == 0) + return 0; + + /* see if pin should be inverted */ + if(pin & PIN_INVERSE) { + pin &= PIN_MASK; + inversion_mask = 1 << (pin - 1); + } else { + inversion_mask = 0; + } + if(TYPE_4232H == ftype) + mlim=7; + else if(TYPE_2232C==ftype) + mlim=11; + else if(TYPE_2232H == ftype) + mlim=15; + else{ + printf("Unknown type %d (0x%x)\n",ftype,ftype); + mlim=15; + } + /* check that the pin number is in range */ + if (pin > mlim) { + fprintf(stderr, + "%s failure: invalid pin definition (pin no > %d) in config file\n", + progname, mlim); + fprintf(stderr, + "pin function no %d, pin no: 0x%x\n", + pinfunc, pin); + return -1; + } + + /* create the mask and check that the pin is available */ + if (pin_direction & (1 << (pin -1)) ) { + fprintf(stderr, + "%s failure: pin %d has two definitions in config file\n", + progname, pin); + return -1; + } else { + pin_direction |= (1 << (pin - 1)); + pin_inversion |= inversion_mask; + } + if(PIN_LED_ERR == pinfunc || + PIN_LED_VFY == pinfunc || + PIN_LED_RDY == pinfunc || + PIN_LED_PGM == pinfunc) { + led_mask|=(1 << (pin - 1)); + } + + return 0; +} + +/* Add pins by pin mask */ + +static int add_pins(PROGRAMMER *pgm, int pinfunc) +{ + int i, pin, mlim; + uint32_t mask, inversion_mask=0; + + pin = pgm->pinno[pinfunc]; + + if(pin & PIN_INVERSE){ + pin &= PIN_MASK; + inversion_mask = pin >>1; + } + pin >>= 1; + if (verbose) + fprintf(stderr, + "add_pins: %d: 0x%04x, inv=0x%04x\n", + pinfunc, pin, inversion_mask); + mask = pin; + if (TYPE_4232H == ftype) + mlim = 8; + else if (TYPE_2232C == ftype) + mlim = 12; + else if (TYPE_2232H == ftype) + mlim = 16; + else{ + printf("Unknown type %d (0x%x)\n", + ftype, ftype); + mlim = 16; + } + if (mask >= 1 << mlim) { + fprintf(stderr, + "%s failure: pin list has pins out of range (%x>%x): ", + progname, mask, 1 << mlim); + mask &= ~(1 << mlim) - 1; + } + else if (mask & pin_direction) { + fprintf(stderr, + "%s failure: conflicting pins in pin list: ", + progname); + mask &= pin_direction; + } + else { + pin_direction |= (uint16_t)mask; + pin_inversion |= inversion_mask; + return 0; + } + + /* print the list of pins, if needed */ + i = 0; + while (mask > 1) { + if (mask & 1) + fprintf(stderr, "%d, ", i); + mask >>= 1; + i++; + } + if (mask > 0) + fprintf(stderr, "%d\n", i); + return -1; +} + + +static int write_flush(void) +{ + unsigned char buf[6]; + if(verbose > 2) + fprintf(stderr, + "%s info: direction: 0x%04x, value: 0x%04x, inversion: 0x%04x\n", + progname, pin_direction, pin_value, pin_inversion); + + buf[0] = 0x80; + buf[1] = pin_value & 0xff; + buf[2] = pin_direction & 0xff; + buf[3] = 0x82; + buf[4] = (pin_value >> 8) & 0xff; + buf[5] = (pin_direction >> 8) & 0xff; + +#ifndef DRYRUN + E(ftdi_write_data(&ftdic, buf, 6) != 6); + +#endif + + if (verbose > 3) + printf("FTDI LOG: %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + /* we need to flush here, because set_pin is used as reset. + * if we want to sleep reset periods, we must be certain the + * avr has got the reset signal when we start sleeping. + * (it may be stuck in the USB stack or some USB hub) + */ + E(ftdi_usb_purge_buffers(&ftdic)); + + return 0; + +} + +/* this function sets or clears a GPIO pin */ +static int set_pin(int pin, int value) +{ + int bit; + uint16_t tval; + if (0 == pin){ + if(verbose > 2) + fprintf(stderr, + "%s info: Pin is zero val %d!\n", + progname, value); + return 1; + } + --pin; + bit= 1 << (pin); + if (pin_inversion & bit) { + value = !value; + } + if (value) + value = bit; + + if (verbose > 1) + fprintf(stderr, + "%s info: pin %04x bit %04x value 0x%04x\n", + progname, pin + 1, bit, value); + /* set bits depending on value */ + /*pin_value ^= (-value ^ pin_value) & (1 << (pin - 1)); */ + tval = (pin_value & (~bit)) | value; + if (tval != pin_value) { + pin_value = tval; + return write_flush(); + } else if (verbose > 1) + fprintf(stderr, "SameVal\n"); + return 0; + +} + +/* this function sets or clears one or more GPIO pin these are bit-mapped */ +static int set_pins(int pin, int value) +{ + if (0 == pin) { + if(verbose > 2) + fprintf(stderr,"%s info: Pins is zero!\n",progname); + return 1; + } + pin >>=1; + if (pin_inversion & pin) { + value = !value; + } + if (value) + value = pin; + + if (verbose) + fprintf(stderr, + "%s info: pin %04x value %d\n", + progname, pin, value); + /* set bits depending on value */ + /*pin_value ^= (-value ^ pin_value) & (1 << (pin - 1)); */ + pin_value = (pin_value & (~pin)) | value; + return write_flush(); +} + +/* these functions are callbacks, which go into the + * PROGRAMMER data structure ("optional functions") + */ +static int set_led_pgm(struct programmer_t * pgm, int value) +{ + return set_pin(pgm->pinno[PIN_LED_PGM], value); +} + +static int set_led_rdy(struct programmer_t * pgm, int value) +{ + return set_pin(pgm->pinno[PIN_LED_RDY], value); +} + +static int set_led_err(struct programmer_t * pgm, int value) +{ + return set_pin(pgm->pinno[PIN_LED_ERR], value); +} + +static int set_led_vfy(struct programmer_t * pgm, int value) +{ + return set_pin(pgm->pinno[PIN_LED_VFY], value); +} + +static int avrftdi_transmit(unsigned char mode, unsigned char *cmd, + unsigned char *data, int buf_size) +{ + int k = 0; + int n; + unsigned char buf[4 + buf_size]; + + if (mode & TX) { + buf[0] = mode; + buf[1] = ((buf_size - 1) & 0xff); + buf[2] = (((buf_size - 1) >> 8) & 0xff); + + memcpy(buf + 3, cmd, buf_size); + buf[buf_size + 3] = 0x87; + +#ifndef DRYRUN + E(ftdi_write_data(&ftdic, buf, buf_size + 4) != buf_size + 4); +#endif + } + + if (mode & RX) { + memset(buf, 0, sizeof(buf)); + do { +#ifndef DRYRUN + n = ftdi_read_data(&ftdic, buf + k, buf_size - k); + E(n < 0); +#else + n = buf_size - k; +#endif + k += n; + } while (k < buf_size); + + memcpy(data, buf, buf_size); + } + + return k; +} + +static int avrftdi_open(PROGRAMMER * pgm, char *port) +{ + int vid, pid, interface, snfound; + char serial[255], *foundsn; + struct ftdi_device_list* devlist; + struct ftdi_device_list* devlist_ptr; + struct usb_device *found_dev; + /* use vid/pid in following priority: config, + * defaults. cmd-line is currently not supported */ + type = 0; + snfound = 0; + foundsn = NULL; + + if (pgm->usbvid) + vid = pgm->usbvid; + else + vid = 0x0403; + + if (pgm->usbpid) + pid = pgm->usbpid; + else + pid = 0x6010; + + if (0 == pgm->usbsn[0]) /* we don't care about SN. Use first avail. */ + snfound = 1; + + if (pgm->usbdev[0] == 'a' || pgm->usbdev[0] == 'A') + interface = INTERFACE_A; + else if (pgm->usbdev[0] == 'b' || pgm->usbdev[0] == 'B') + interface = INTERFACE_B; + else { + fprintf(stderr, + "%s: Invalid interface '%s'. Setting to Interface A\n", + progname, pgm->usbdev); + interface = INTERFACE_A; + } +#ifndef DRYRUN + E(ftdi_init(&ftdic) < 0); + found_dev = NULL; + if (ftdi_usb_find_all(&ftdic, &devlist, vid, pid)) { + devlist_ptr = devlist; + do { + ftdi_usb_get_strings(&ftdic, devlist_ptr->dev, + NULL, 0, NULL, 0, serial, 255); + + if (verbose) + fprintf(stderr, + "%s: device: %s, serial number: %s type 0x%04x found\n", + progname, devlist_ptr->dev->filename, + serial, devlist_ptr->dev->descriptor.bcdDevice); + + if (!snfound) { + if (strcmp(pgm->usbsn, serial) == 0){ + foundsn = strdup(serial); + snfound = 1; + found_dev = devlist_ptr->dev; + type = devlist_ptr->dev->descriptor.bcdDevice; + } + }else { + if (0 == type) /**we assume it will attach to first found. */ + type = devlist_ptr->dev->descriptor.bcdDevice; + if (NULL == found_dev) + found_dev = devlist_ptr->dev; + if (NULL == foundsn) + foundsn = strdup(serial); + } + memset(serial, 0, 255); + devlist_ptr = devlist_ptr->next; + } while (devlist_ptr); + } else { + fprintf(stderr, + "%s: No devices with Vendor-ID:Product-ID %04x:%04x found.\n", + progname, vid, pid); + ftdi_list_free(&devlist); + return -1; + } + if (!snfound) { + fprintf(stderr, + "%s: No devices with VID:PID %04x:%04x and SN '%s' found.\n", + progname, vid, pid, pgm->usbsn); + ftdi_list_free(&devlist); + return -1; + } + if (verbose) { + fprintf(stderr, + "%s: Using device VID:PID %04x:%04x type 0x%04x(", + progname, vid, pid, type); + switch (type) { + case TYPE_C_D: + fprintf(stderr,"C/D"); break; + case TYPE_H: + fprintf(stderr,"H"); break; + case TYPE_4H: + fprintf(stderr,"4H"); break; + default: + fprintf(stderr,"unknown %04x",type); break; + } + + fprintf(stderr,") and SN '%s'.\n", foundsn); + } + if (type == TYPE_C_D && INTERFACE_B == interface){ + fprintf(stderr, + "%s: Type C/D found. Setting interface to A\n", + progname); + interface = INTERFACE_A; + } + /*must be A for mpsse if C/D, can be A/B for H */ + if (verbose) + fprintf(stderr, + "%s: Using USB Interface %c\n", + progname, INTERFACE_A == interface? 'A': 'B'); + free(foundsn); + E(ftdi_set_interface(&ftdic, interface) < 0); + E(ftdi_usb_open_dev(&ftdic,found_dev) <0); +/* E(ftdi_usb_open_desc(&ftdic, vid,pid,NULL,0==pgm->usbsn[0]?NULL:pgm->usbsn) < 0); */ + ftype=ftdic.type; +#endif + + + if (SCK != (1 << (pgm->pinno[PIN_AVR_SCK] - 1)) + || SDO != (1 << (pgm->pinno[PIN_AVR_MOSI] - 1)) + || SDI != (1 << (pgm->pinno[PIN_AVR_MISO] - 1))) { + fprintf(stderr, + "%s failure: pinning for FTDI MPSSE must be:\n" + "\tSCK: 1, SDO: 2, SDI: 3(is: %d,%d,%d)\n", + progname, + pgm->pinno[PIN_AVR_SCK], + pgm->pinno[PIN_AVR_MOSI], + pgm->pinno[PIN_AVR_MISO]); + fprintf(stderr, "Setting pins accordingly ...\n"); + pgm->pinno[PIN_AVR_SCK] = 1; + pgm->pinno[PIN_AVR_MOSI] = 2; + pgm->pinno[PIN_AVR_MISO] = 3; + + } + if(verbose) + fprintf(stderr, + "%s info: reset pin value: %x\n", + progname, pgm->pinno[PIN_AVR_RESET]-1); + if (pgm->pinno[PIN_AVR_RESET] < 4 || pgm->pinno[PIN_AVR_RESET] == 0) { + fprintf(stderr, + "%s failure: RESET pin clashes with data pin or is not set.\n", + progname); + fprintf(stderr, "Setting to default-value 4\n"); + pgm->pinno[PIN_AVR_RESET] = 4; + } + /**sync our internal state with the chip */ + pin_direction = 0; + pin_value = 0; + write_flush(); + pin_direction = (0x3 | (1 << (pgm->pinno[PIN_AVR_RESET] - 1))); + + /* gather the rest of the pins */ + if (add_pins(pgm, PPI_AVR_VCC)) return -1; + if (add_pins(pgm, PPI_AVR_BUFF)) return -1; + if (add_pin(pgm, PIN_LED_ERR)) return -1; + if (add_pin(pgm, PIN_LED_RDY)) return -1; + if (add_pin(pgm, PIN_LED_PGM)) return -1; + if (add_pin(pgm, PIN_LED_VFY)) return -1; +#ifndef DRYRUN + E(ftdi_set_bitmode(&ftdic, pin_direction & 0xff, BITMODE_MPSSE) < 0); /*set SPI */ +#endif + if (verbose > 1) { + fprintf(stderr, "pin direction mask: %04x\n", pin_direction); + fprintf(stderr, "pin value mask: %04x\n", pin_value); + } + + if (pgm->baudrate) { + set_frequency(pgm->baudrate); + } else if(pgm->bitclock) { + set_frequency((uint32_t)(1.0f/pgm->bitclock)); + } else { + set_frequency(pgm->baudrate ? pgm->baudrate : 150000); + } + /**set the ready LED, if we have one .. and set our direction up */ + set_led_rdy(pgm,0); + set_led_rdy(pgm,1); + return 0; +} + +static void avrftdi_close(PROGRAMMER * pgm) +{ + if(ftdic.usb_dev) { + set_pins(pgm->pinno[PPI_AVR_BUFF], ON); + set_pin(pgm->pinno[PIN_AVR_RESET], ON); + /**Stop driving the pins - except for the LEDs */ + if (verbose > 1) + fprintf(stderr, + "LED Mask=0x%04x value =0x%04x &=0x%04x\n", + led_mask, pin_value, led_mask & pin_value); + pin_direction = led_mask; + pin_value &= led_mask; + write_flush(); +#ifndef DRYRUN + E_VOID(ftdi_usb_close(&ftdic)); +#endif + } + +#ifndef DRYRUN + ftdi_deinit(&ftdic); +#endif + + return; +} + + +static int avrftdi_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + set_pin(pgm->pinno[PIN_AVR_RESET], OFF); + set_pins(pgm->pinno[PPI_AVR_BUFF], OFF); + set_pin(pgm->pinno[PIN_AVR_SCK], OFF); + /*use speed optimization with CAUTION*/ + usleep(20 * 1000); + + /* giving rst-pulse of at least 2 avr-clock-cycles, for + * security (2us @ 1MHz) */ + set_pin(pgm->pinno[PIN_AVR_RESET], ON); + usleep(20 * 1000); + + /*setting rst back to 0 */ + set_pin(pgm->pinno[PIN_AVR_RESET], OFF); + /*wait at least 20ms bevor issuing spi commands to avr */ + usleep(20 * 1000); + + return pgm->program_enable(pgm, p); +} + +static void avrftdi_disable(PROGRAMMER * pgm) +{ + return; +} + +static void avrftdi_enable(PROGRAMMER * pgm) +{ + return; +} + +static void avrftdi_display(PROGRAMMER * pgm, const char *p) +{ + return; +} + + +static int avrftdi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) +{ + return avrftdi_transmit(TRX, cmd, res, sizeof(cmd)); +} + + +static int avrftdi_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + int i; + unsigned char buf[4]; + + memset(buf, 0, sizeof(buf)); + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) { + fprintf(stderr, + "%s failure: Program Enable (PGM_ENABLE) command not defined for %s\n", + progname, p->desc); + return -1; + } + + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf); + + for(i = 0; i < 4; i++) { + pgm->cmd(pgm, buf, buf); + if (buf[p->pollindex-1] != p->pollvalue) { + //try resetting + set_pin(pgm->pinno[PIN_AVR_RESET], ON); + usleep(20); + set_pin(pgm->pinno[PIN_AVR_RESET], OFF); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf); + } else + return 0; + } +#ifndef DRYRUN + return -1; +#else + return 0; +#endif +} + + +static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, + "%s failure Chip Erase (CHIP_ERASE) command not defined for %s\n", + progname, p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + return 0; +} + + +/* Load extended address byte command */ +static int avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, int address) +{ + unsigned char buf[] = {0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; + + avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], &buf[3]); + avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], &buf[3], address); + + if(verbose > 1) + buf_dump(buf, sizeof(buf), + "load extended address command", 0, 16 * 3); + +#ifndef DRYRUN + E(ftdi_write_data(&ftdic, buf, sizeof(buf)) != sizeof(buf)); +#endif + return 0; +} + +static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + int page_size, int len) +{ + unsigned char cmd[4]; + unsigned char *data = m->buf; + int add; + + avr_set_bits(m->op[AVR_OP_WRITE], cmd); + + for (add = 0; add < len; add++) + { + avr_set_addr(m->op[AVR_OP_WRITE], cmd, add); + avr_set_input(m->op[AVR_OP_WRITE], cmd, *data++); + + E(avrftdi_transmit(TX, cmd, cmd, 4) < 0); + + usleep((m->max_write_delay)); + if(verbose < 3) + report_progress(add, len, NULL); + } + return len; +} + +static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + int page_size, int len) +{ + unsigned char cmd[4]; + unsigned char buffer[len], *bufptr = buffer; + + int add; + + memset(buffer, 0, sizeof(buffer)); + + for (add = 0; add < len; add++) + { + avr_set_bits(m->op[AVR_OP_READ], cmd); + avr_set_addr(m->op[AVR_OP_READ], cmd, add); + + E(avrftdi_transmit(TRX, cmd, cmd, 4) < 0); + + avr_get_output(m->op[AVR_OP_READ], cmd, bufptr++); + if(verbose < 3) + report_progress(add, len, NULL); + } + + memcpy(m->buf, buffer, len); + return len; +} + +static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int len) +{ + int i; + int address = 0, buf_size; + int bytes = len; + int blocksize; + int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; + unsigned char *buf, *bufptr; + unsigned char *buffer = m->buf; + unsigned char byte; + + + buf = (unsigned char*) malloc(4 * len + 4); + if (buf == NULL) { + fprintf(stderr, + "%s (avrftdi_flash_write): error allocating memory\n", + p->desc); + exit (-1); + } + + bufptr = buf; + + /* pre-check opcodes */ + if (m->op[AVR_OP_LOADPAGE_LO] == NULL) { + fprintf(stderr, + "%s failure: %s command not defined for %s\n", + progname, "AVR_OP_LOADPAGE_LO", p->desc); + return -1; + } + if (m->op[AVR_OP_LOADPAGE_HI] == NULL) { + fprintf(stderr, + "%s failure: %s command not defined for %s\n", + progname, "AVR_OP_LOADPAGE_HI", p->desc); + return -1; + } + + //page_size = (page_size > m->page_size) ? m->page_size : page_size - 8; + page_size = m->page_size; + + while (bytes) { + if (bytes > page_size) { + blocksize = (page_size)/2; + bytes -= (page_size); + } else { + blocksize = bytes/2; + bytes = 0; + } + + if(verbose > 2) + fprintf(stderr, + "-< bytes = %d of %d, blocksize = %d of %d\n", + len - bytes, len, blocksize, m->page_size / 2); + + /* if we do cross a 64k word boundary (or write the + * first page), we need to issue a 'load extended + * address byte' command, which is defined as 0x4d + * 0x00
0x00. As far as i know, this + * is only available on 256k parts. 64k word is 128k + * bytes. + */ + if (use_lext_address && !(bytes & 0x1ffff)) { + avrftdi_lext(pgm, p, m, address); + } + + for (i = 0; i < blocksize; i++) { + /*setting word*/ + avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], bufptr); + avr_set_addr(m->op[AVR_OP_LOADPAGE_LO], bufptr, address); + avr_set_input(m->op[AVR_OP_LOADPAGE_LO], bufptr, *buffer++); + bufptr += 4; + avr_set_bits(m->op[AVR_OP_LOADPAGE_HI], bufptr); + avr_set_addr(m->op[AVR_OP_LOADPAGE_HI], bufptr, address); + avr_set_input(m->op[AVR_OP_LOADPAGE_HI], bufptr, *buffer++); + bufptr += 4; + address++; + } + + if (verbose > 2) + fprintf(stderr, + "address = %d, page_size = %d\n", + address, m->page_size); + + if (((address * 2) % m->page_size) == 0 || bytes == 0) { + if (m->op[AVR_OP_WRITEPAGE] == NULL) { + fprintf(stderr, + "%s failure: Write Page (WRITEPAGE) command not defined for %s\n", + progname, p->desc); + exit(1); + } else { + avr_set_bits(m->op[AVR_OP_WRITEPAGE], bufptr); + } + /* setting page address highbyte */ + avr_set_addr(m->op[AVR_OP_WRITEPAGE], + bufptr, address - 1); + bufptr += 4; + } + + buf_size = bufptr - buf; + + if(verbose > 3) + buf_dump(buf, buf_size, "command buffer", 0, 16*3); + if(verbose > 2) + fprintf(stderr, + "%s info: buffer size: %d\n", + progname, buf_size); + + E(avrftdi_transmit(TX, buf, buf, buf_size) < 0); + + bufptr = buf; + if (((address * 2) % m->page_size) == 0 || bytes == 0) { + do { + pgm->read_byte(pgm, p, m, + (address * 2) - 1, &byte); + } while (m->buf[(address*2) - 1] != byte); + } + + if (verbose < 3) + report_progress(2 * address, len, NULL); + } + return len; +} + +static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int len) +{ + /* + *Reading from flash + */ + int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; + int i, buf_index, buf_size = 0, psize = m->page_size; + unsigned char o_buf[4*len+4], *o_ptr = o_buf; + unsigned char i_buf[4*len+4]; + int address = 0; + int bytes = len; + int blocksize; + unsigned char buffer[m->size], *bufptr = buffer; + + memset(o_buf, 0, sizeof(o_buf)); + memset(i_buf, 0, sizeof(i_buf)); + memset(buffer, 0, sizeof(buffer)); + + /* pre-check opcodes */ + if (m->op[AVR_OP_READ_LO] == NULL) { + fprintf(stderr, + "%s failure: %s command not defined for %s\n", + progname, "AVR_OP_READ_LO", p->desc); + return -1; + } + if (m->op[AVR_OP_READ_HI] == NULL) { + fprintf(stderr, + "%s failure: %s command not defined for %s\n", + progname, "AVR_OP_READ_HI", p->desc); + return -1; + } + + while (bytes) { + if (bytes > psize) { + blocksize = psize/2; + bytes -= psize; + } else { + blocksize = bytes/2; + bytes = 0; + } + + if(use_lext_address && !(bytes & 0x1ffff)) { + avrftdi_lext(pgm, p, m, address); + } + + for(i = 0; i < blocksize; i++) { + if(verbose > 3) + fprintf(stderr, + "bufsize: %d, i: %d, add: %d\n", + buf_size, i, address); + avr_set_bits(m->op[AVR_OP_READ_LO], o_ptr); + avr_set_addr(m->op[AVR_OP_READ_LO], o_ptr, address); + o_ptr += 4; + avr_set_bits(m->op[AVR_OP_READ_HI], o_ptr); + avr_set_addr(m->op[AVR_OP_READ_HI], o_ptr, address); + o_ptr += 4; + + address++; + + //FIXME: why not program on per-page basis? + //maybe this covered a timing error in an earlier version? + buf_size = o_ptr - o_buf; + + if((buf_size >= (page_size - 8)) || ( i == blocksize-1)) { + E(avrftdi_transmit(TRX, o_buf, i_buf, buf_size) < 0); + + for(buf_index = 0; buf_index < buf_size; buf_index+=8) { + avr_get_output(m->op[AVR_OP_READ_LO], i_buf+buf_index, bufptr++); + avr_get_output(m->op[AVR_OP_READ_HI], i_buf+buf_index+4, bufptr++); + } + + if(verbose > 3) { + buf_dump(i_buf, buf_size, "i_buf", 0, 16); + } + o_ptr = o_buf; + } + } + if (verbose < 3) + report_progress(2 * address, len, NULL); + } + memcpy(m->buf, buffer, sizeof(buffer)); + + return len; +} + +static int avrftdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + if (strcmp(m->desc, "flash") == 0) + return avrftdi_flash_write(pgm, p, m, page_size, n_bytes); + else if (strcmp(m->desc, "eeprom") == 0) + return avrftdi_eeprom_write(pgm, p, m, page_size, n_bytes); + else + return -2; +} + +static int avrftdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + if (strcmp(m->desc, "flash") == 0) + return avrftdi_flash_read(pgm, p, m, page_size, n_bytes); + else if(strcmp(m->desc, "eeprom") == 0) + return avrftdi_eeprom_read(pgm, p, m, page_size, n_bytes); + else + return -2; +} + +void avrftdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "avrftdi"); + + pin_value=pin_direction=pin_inversion=led_mask=0; + /* + * mandatory functions + */ + + pgm->initialize = avrftdi_initialize; + pgm->display = avrftdi_display; + pgm->enable = avrftdi_enable; + pgm->disable = avrftdi_disable; + pgm->program_enable = avrftdi_program_enable; + pgm->chip_erase = avrftdi_chip_erase; + pgm->cmd = avrftdi_cmd; + pgm->open = avrftdi_open; + pgm->close = avrftdi_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + + pgm->paged_write = avrftdi_paged_write; + pgm->paged_load = avrftdi_paged_load; + + pgm->rdy_led = set_led_rdy; + pgm->err_led = set_led_err; + pgm->pgm_led = set_led_pgm; + pgm->vfy_led = set_led_vfy; + + +} + +#else /*HAVE_LIBFTDI*/ + +static int avrftdi_noftdi_open (struct programmer_t *pgm, char * name) +{ + fprintf(stderr, + "%s: error: no libftdi support. please compile again with libftdi installed.\n", + progname); + + exit(1); +} + +void avrftdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "avrftdi"); + pgm->open = avrftdi_noftdi_open; +} + +#endif /* HAVE_LIBFTDI */ + +#else /*HAVE_LIBUSB*/ + +static int avrftdi_nousb_open (struct programmer_t *pgm, char * name) +{ + fprintf(stderr, + "%s: error: no usb support. please compile again with libusb installed.\n", + progname); + + exit(1); +} + +void avrftdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "avrftdi"); + pgm->open = avrftdi_nousb_open; +} + +#endif /*HAVE_LIBUSB*/ + diff --git a/avrdude/avrftdi.h b/avrdude/avrftdi.h new file mode 100644 index 00000000..b1ffc893 --- /dev/null +++ b/avrdude/avrftdi.h @@ -0,0 +1,56 @@ +/* + * avrftdi - extension for avrdude, Wolfgang Moser, Ville Voipio + * Copyright (C) 2011 Hannes Weisbach, Doug Springer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef avrftdi_h +#define avrfdti_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define SCK 0x01 +#define SDO 0x02 +#define SDI 0x04 + +#define RX 0x20 +#define TX 0x11 + +#define TRX (RX | TX) + +#define TYPE_C_D 0x500 +#define TYPE_H 0x700 +#define TYPE_4H 0x800 + +#define E(x) if ((x)) { fprintf(stdout, "%s:%d %s() %s: %s (%d)\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, \ + #x, strerror(errno), errno, ftdi_get_error_string(&ftdic)); return -1; } + +#define E_VOID(x) if ((x)) { fprintf(stdout, "%s:%d %s() %s: %s (%d)\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, \ + #x, strerror(errno), errno, ftdi_get_error_string(&ftdic)); } + +void avrftdi_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/avrdude/avrpart.c b/avrdude/avrpart.c new file mode 100644 index 00000000..61994aac --- /dev/null +++ b/avrdude/avrpart.c @@ -0,0 +1,547 @@ + +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include +#include + +#include "avrdude.h" +#include "avrpart.h" +#include "pindefs.h" + +/*** + *** Elementary functions dealing with OPCODE structures + ***/ + +OPCODE * avr_new_opcode(void) +{ + OPCODE * m; + + m = (OPCODE *)malloc(sizeof(*m)); + if (m == NULL) { + fprintf(stderr, "avr_new_opcode(): out of memory\n"); + exit(1); + } + + memset(m, 0, sizeof(*m)); + + return m; +} + + +/* + * avr_set_bits() + * + * Set instruction bits in the specified command based on the opcode. + */ +int avr_set_bits(OPCODE * op, unsigned char * cmd) +{ + int i, j, bit; + unsigned char mask; + + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_VALUE) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + if (op->bit[i].value) + cmd[j] = cmd[j] | mask; + else + cmd[j] = cmd[j] & ~mask; + } + } + + return 0; +} + + +/* + * avr_set_addr() + * + * Set address bits in the specified command based on the opcode, and + * the address. + */ +int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr) +{ + int i, j, bit; + unsigned long value; + unsigned char mask; + + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_ADDRESS) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + value = addr >> op->bit[i].bitno & 0x01; + if (value) + cmd[j] = cmd[j] | mask; + else + cmd[j] = cmd[j] & ~mask; + } + } + + return 0; +} + + +/* + * avr_set_input() + * + * Set input data bits in the specified command based on the opcode, + * and the data byte. + */ +int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data) +{ + int i, j, bit; + unsigned char value; + unsigned char mask; + + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_INPUT) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + value = data >> op->bit[i].bitno & 0x01; + if (value) + cmd[j] = cmd[j] | mask; + else + cmd[j] = cmd[j] & ~mask; + } + } + + return 0; +} + + +/* + * avr_get_output() + * + * Retreive output data bits from the command results based on the + * opcode data. + */ +int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data) +{ + int i, j, bit; + unsigned char value; + unsigned char mask; + + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_OUTPUT) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + value = ((res[j] & mask) >> bit) & 0x01; + value = value << op->bit[i].bitno; + if (value) + *data = *data | value; + else + *data = *data & ~value; + } + } + + return 0; +} + + +static char * avr_op_str(int op) +{ + switch (op) { + case AVR_OP_READ : return "READ"; break; + case AVR_OP_WRITE : return "WRITE"; break; + case AVR_OP_READ_LO : return "READ_LO"; break; + case AVR_OP_READ_HI : return "READ_HI"; break; + case AVR_OP_WRITE_LO : return "WRITE_LO"; break; + case AVR_OP_WRITE_HI : return "WRITE_HI"; break; + case AVR_OP_LOADPAGE_LO : return "LOADPAGE_LO"; break; + case AVR_OP_LOADPAGE_HI : return "LOADPAGE_HI"; break; + case AVR_OP_LOAD_EXT_ADDR : return "LOAD_EXT_ADDR"; break; + case AVR_OP_WRITEPAGE : return "WRITEPAGE"; break; + case AVR_OP_CHIP_ERASE : return "CHIP_ERASE"; break; + case AVR_OP_PGM_ENABLE : return "PGM_ENABLE"; break; + default : return ""; break; + } +} + + +static char * bittype(int type) +{ + switch (type) { + case AVR_CMDBIT_IGNORE : return "IGNORE"; break; + case AVR_CMDBIT_VALUE : return "VALUE"; break; + case AVR_CMDBIT_ADDRESS : return "ADDRESS"; break; + case AVR_CMDBIT_INPUT : return "INPUT"; break; + case AVR_CMDBIT_OUTPUT : return "OUTPUT"; break; + default : return ""; break; + } +} + + + +/*** + *** Elementary functions dealing with AVRMEM structures + ***/ + +AVRMEM * avr_new_memtype(void) +{ + AVRMEM * m; + + m = (AVRMEM *)malloc(sizeof(*m)); + if (m == NULL) { + fprintf(stderr, "avr_new_memtype(): out of memory\n"); + exit(1); + } + + memset(m, 0, sizeof(*m)); + + return m; +} + + +/* + * Allocate and initialize memory buffers for each of the device's + * defined memory regions. + */ +int avr_initmem(AVRPART * p) +{ + LNODEID ln; + AVRMEM * m; + + for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + m->buf = (unsigned char *) malloc(m->size); + if (m->buf == NULL) { + fprintf(stderr, "%s: can't alloc buffer for %s size of %d bytes\n", + progname, m->desc, m->size); + return -1; + } + } + + return 0; +} + + +AVRMEM * avr_dup_mem(AVRMEM * m) +{ + AVRMEM * n; + + n = avr_new_memtype(); + + *n = *m; + + n->buf = (unsigned char *)malloc(n->size); + if (n->buf == NULL) { + fprintf(stderr, + "avr_dup_mem(): out of memory (memsize=%d)\n", + n->size); + exit(1); + } + memset(n->buf, 0, n->size); + + return n; +} + + +AVRMEM * avr_locate_mem(AVRPART * p, char * desc) +{ + AVRMEM * m, * match; + LNODEID ln; + int matches; + int l; + + l = strlen(desc); + matches = 0; + match = NULL; + for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + if (strncmp(desc, m->desc, l) == 0) { + match = m; + matches++; + } + } + + if (matches == 1) + return match; + + return NULL; +} + + +void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type, + int verbose) +{ + int i, j; + char * optr; + + if (m == NULL) { + fprintf(f, + "%s Block Poll Page Polled\n" + "%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n" + "%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n", + prefix, prefix, prefix); + } + else { + if (verbose > 2) { + fprintf(f, + "%s Block Poll Page Polled\n" + "%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n" + "%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n", + prefix, prefix, prefix); + } + fprintf(f, + "%s%-11s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n", + prefix, m->desc, m->mode, m->delay, m->blocksize, m->pollindex, + m->paged ? "yes" : "no", + m->size, + m->page_size, + m->num_pages, + m->min_write_delay, + m->max_write_delay, + m->readback[0], + m->readback[1]); + if (verbose > 4) { + fprintf(stderr, + "%s Memory Ops:\n" + "%s Oeration Inst Bit Bit Type Bitno Value\n" + "%s ----------- -------- -------- ----- -----\n", + prefix, prefix, prefix); + for (i=0; iop[i]) { + for (j=31; j>=0; j--) { + if (j==31) + optr = avr_op_str(i); + else + optr = " "; + fprintf(f, + "%s %-11s %8d %8s %5d %5d\n", + prefix, optr, j, + bittype(m->op[i]->bit[j].type), + m->op[i]->bit[j].bitno, + m->op[i]->bit[j].value); + } + } + } + } + } +} + + + +/* + * Elementary functions dealing with AVRPART structures + */ + + +AVRPART * avr_new_part(void) +{ + AVRPART * p; + + p = (AVRPART *)malloc(sizeof(AVRPART)); + if (p == NULL) { + fprintf(stderr, "new_part(): out of memory\n"); + exit(1); + } + + memset(p, 0, sizeof(*p)); + + p->id[0] = 0; + p->desc[0] = 0; + p->reset_disposition = RESET_DEDICATED; + p->retry_pulse = PIN_AVR_SCK; + p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING; + p->config_file[0] = 0; + p->lineno = 0; + memset(p->signature, 0xFF, 3); + p->ctl_stack_type = CTL_STACK_NONE; + + p->mem = lcreat(NULL, 0); + + return p; +} + + +AVRPART * avr_dup_part(AVRPART * d) +{ + AVRPART * p; + LISTID save; + LNODEID ln; + + p = avr_new_part(); + save = p->mem; + + *p = *d; + + p->mem = save; + + for (ln=lfirst(d->mem); ln; ln=lnext(ln)) { + ladd(p->mem, avr_dup_mem(ldata(ln))); + } + + return p; +} + + +AVRPART * locate_part(LISTID parts, char * partdesc) +{ + LNODEID ln1; + AVRPART * p = NULL; + int found; + + found = 0; + + for (ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) { + p = ldata(ln1); + if ((strcasecmp(partdesc, p->id) == 0) || + (strcasecmp(partdesc, p->desc) == 0)) + found = 1; + } + + if (found) + return p; + + return NULL; +} + +AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode) +{ + LNODEID ln1; + AVRPART * p = NULL; + + for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) { + p = ldata(ln1); + if (p->avr910_devcode == devcode) + return p; + } + + return NULL; +} + +/* + * Iterate over the list of avrparts given as "avrparts", and + * call the callback function cb for each entry found. cb is being + * passed the following arguments: + * . the name of the avrpart (for -p) + * . the descriptive text given in the config file + * . the name of the config file this avrpart has been defined in + * . the line number of the config file this avrpart has been defined at + * . the "cookie" passed into walk_avrparts() (opaque client data) + */ +void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie) +{ + LNODEID ln1; + AVRPART * p; + + for (ln1 = lfirst(avrparts); ln1; ln1 = lnext(ln1)) { + p = ldata(ln1); + cb(p->id, p->desc, p->config_file, p->lineno, cookie); + } +} + + + +static char * reset_disp_str(int r) +{ + switch (r) { + case RESET_DEDICATED : return "dedicated"; + case RESET_IO : return "possible i/o"; + default : return ""; + } +} + + +static char * pin_name(int pinno) +{ + switch (pinno) { + case PIN_AVR_RESET : return "RESET"; + case PIN_AVR_MISO : return "MISO"; + case PIN_AVR_MOSI : return "MOSI"; + case PIN_AVR_SCK : return "SCK"; + default : return ""; + } +} + + +void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose) +{ + int i; + char * buf; + const char * px; + LNODEID ln; + AVRMEM * m; + + fprintf(f, + "%sAVR Part : %s\n" + "%sChip Erase delay : %d us\n" + "%sPAGEL : P%02X\n" + "%sBS2 : P%02X\n" + "%sRESET disposition : %s\n" + "%sRETRY pulse : %s\n" + "%sserial program mode : %s\n" + "%sparallel program mode : %s\n" + "%sTimeout : %d\n" + "%sStabDelay : %d\n" + "%sCmdexeDelay : %d\n" + "%sSyncLoops : %d\n" + "%sByteDelay : %d\n" + "%sPollIndex : %d\n" + "%sPollValue : 0x%02x\n" + "%sMemory Detail :\n\n", + prefix, p->desc, + prefix, p->chip_erase_delay, + prefix, p->pagel, + prefix, p->bs2, + prefix, reset_disp_str(p->reset_disposition), + prefix, pin_name(p->retry_pulse), + prefix, (p->flags & AVRPART_SERIALOK) ? "yes" : "no", + prefix, (p->flags & AVRPART_PARALLELOK) ? + ((p->flags & AVRPART_PSEUDOPARALLEL) ? "psuedo" : "yes") : "no", + prefix, p->timeout, + prefix, p->stabdelay, + prefix, p->cmdexedelay, + prefix, p->synchloops, + prefix, p->bytedelay, + prefix, p->pollindex, + prefix, p->pollvalue, + prefix); + + px = prefix; + i = strlen(prefix) + 5; + buf = (char *)malloc(i); + if (buf == NULL) { + /* ugh, this is not important enough to bail, just ignore it */ + } + else { + strcpy(buf, prefix); + strcat(buf, " "); + px = buf; + } + + if (verbose <= 2) { + avr_mem_display(px, f, NULL, 0, verbose); + } + for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + avr_mem_display(px, f, m, i, verbose); + } + + if (buf) + free(buf); +} diff --git a/avrdude/avrpart.h b/avrdude/avrpart.h new file mode 100644 index 00000000..04334609 --- /dev/null +++ b/avrdude/avrpart.h @@ -0,0 +1,225 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Brian S. Dean + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef avrpart_h +#define avrpart_h + +#include + +#include "lists.h" + + +/* + * AVR serial programming instructions + */ +enum { + AVR_OP_READ, + AVR_OP_WRITE, + AVR_OP_READ_LO, + AVR_OP_READ_HI, + AVR_OP_WRITE_LO, + AVR_OP_WRITE_HI, + AVR_OP_LOADPAGE_LO, + AVR_OP_LOADPAGE_HI, + AVR_OP_LOAD_EXT_ADDR, + AVR_OP_WRITEPAGE, + AVR_OP_CHIP_ERASE, + AVR_OP_PGM_ENABLE, + AVR_OP_MAX +}; + + +enum { + AVR_CMDBIT_IGNORE, /* bit is ignored on input and output */ + AVR_CMDBIT_VALUE, /* bit is set to 0 or 1 for input or output */ + AVR_CMDBIT_ADDRESS, /* this bit represents an input address bit */ + AVR_CMDBIT_INPUT, /* this bit is an input bit */ + AVR_CMDBIT_OUTPUT /* this bit is an output bit */ +}; + +enum { /* these are assigned to reset_disposition of AVRPART */ + RESET_DEDICATED, /* reset pin is dedicated */ + RESET_IO /* reset pin might be configured as an I/O pin */ +}; + +enum ctl_stack_t { + CTL_STACK_NONE, /* no control stack defined */ + CTL_STACK_PP, /* parallel programming control stack */ + CTL_STACK_HVSP /* high voltage serial programming control stack */ +}; + +/* + * serial programming instruction bit specifications + */ +typedef struct cmdbit { + int type; /* AVR_CMDBIT_* */ + int bitno; /* which input bit to use for this command bit */ + int value; /* bit value if type == AVR_CMDBIT_VALUD */ +} CMDBIT; + +typedef struct opcode { + CMDBIT bit[32]; /* opcode bit specs */ +} OPCODE; + + +#define AVRPART_SERIALOK 0x0001 /* part supports serial programming */ +#define AVRPART_PARALLELOK 0x0002 /* part supports parallel programming */ +#define AVRPART_PSEUDOPARALLEL 0x0004 /* part has pseudo parallel support */ +#define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */ +#define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */ +#define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */ +#define AVRPART_HAS_DW 0x0040 /* part has a debugWire i/f */ +#define AVRPART_HAS_PDI 0x0080 /* part has PDI i/f rather than ISP (ATxmega) */ +#define AVRPART_AVR32 0x0100 /* part is in AVR32 family */ +#define AVRPART_INIT_SMC 0x0200 /* part will undergo chip erase */ +#define AVRPART_WRITE 0x0400 /* at least one write operation specified */ +#define AVRPART_HAS_TPI 0x0800 /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */ + +#define AVR_DESCLEN 64 +#define AVR_IDLEN 32 +#define CTL_STACK_SIZE 32 +#define FLASH_INSTR_SIZE 3 +#define EEPROM_INSTR_SIZE 20 +typedef struct avrpart { + char desc[AVR_DESCLEN]; /* long part name */ + char id[AVR_IDLEN]; /* short part name */ + int stk500_devcode; /* stk500 device code */ + int avr910_devcode; /* avr910 device code */ + int chip_erase_delay; /* microseconds */ + unsigned char pagel; /* for parallel programming */ + unsigned char bs2; /* for parallel programming */ + unsigned char signature[3]; /* expected value of signature bytes */ + int reset_disposition; /* see RESET_ enums */ + int retry_pulse; /* retry program enable by pulsing + this pin (PIN_AVR_*) */ + unsigned flags; /* see AVRPART_ masks */ + + int timeout; /* stk500 v2 xml file parameter */ + int stabdelay; /* stk500 v2 xml file parameter */ + int cmdexedelay; /* stk500 v2 xml file parameter */ + int synchloops; /* stk500 v2 xml file parameter */ + int bytedelay; /* stk500 v2 xml file parameter */ + int pollindex; /* stk500 v2 xml file parameter */ + unsigned char pollvalue; /* stk500 v2 xml file parameter */ + int predelay; /* stk500 v2 xml file parameter */ + int postdelay; /* stk500 v2 xml file parameter */ + int pollmethod; /* stk500 v2 xml file parameter */ + + enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */ + unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */ + unsigned char flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */ + unsigned char eeprom_instr[EEPROM_INSTR_SIZE]; /* EEPROM instructions (debugWire, JTAG) */ + + int hventerstabdelay; /* stk500 v2 hv mode parameter */ + int progmodedelay; /* stk500 v2 hv mode parameter */ + int latchcycles; /* stk500 v2 hv mode parameter */ + int togglevtg; /* stk500 v2 hv mode parameter */ + int poweroffdelay; /* stk500 v2 hv mode parameter */ + int resetdelayms; /* stk500 v2 hv mode parameter */ + int resetdelayus; /* stk500 v2 hv mode parameter */ + int hvleavestabdelay; /* stk500 v2 hv mode parameter */ + int resetdelay; /* stk500 v2 hv mode parameter */ + int chiperasepulsewidth; /* stk500 v2 hv mode parameter */ + int chiperasepolltimeout; /* stk500 v2 hv mode parameter */ + int chiperasetime; /* stk500 v2 hv mode parameter */ + int programfusepulsewidth; /* stk500 v2 hv mode parameter */ + int programfusepolltimeout; /* stk500 v2 hv mode parameter */ + int programlockpulsewidth; /* stk500 v2 hv mode parameter */ + int programlockpolltimeout; /* stk500 v2 hv mode parameter */ + int synchcycles; /* stk500 v2 hv mode parameter */ + int hvspcmdexedelay; /* stk500 v2 xml file parameter */ + + unsigned char idr; /* JTAG ICE mkII XML file parameter */ + unsigned char rampz; /* JTAG ICE mkII XML file parameter */ + unsigned char spmcr; /* JTAG ICE mkII XML file parameter */ + unsigned short eecr; /* JTAC ICE mkII XML file parameter */ + unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */ + + OPCODE * op[AVR_OP_MAX]; /* opcodes */ + + LISTID mem; /* avr memory definitions */ + char config_file[PATH_MAX]; /* config file where defined */ + int lineno; /* config file line number */ +} AVRPART; + +#define AVR_MEMDESCLEN 64 +typedef struct avrmem { + char desc[AVR_MEMDESCLEN]; /* memory description ("flash", "eeprom", etc) */ + int paged; /* page addressed (e.g. ATmega flash) */ + int size; /* total memory size in bytes */ + int page_size; /* size of memory page (if page addressed) */ + int num_pages; /* number of pages (if page addressed) */ + unsigned int offset; /* offset in IO memory (ATxmega) */ + int min_write_delay; /* microseconds */ + int max_write_delay; /* microseconds */ + int pwroff_after_write; /* after this memory type is written to, + the device must be powered off and + back on, see errata + http://www.atmel.com/atmel/acrobat/doc1280.pdf */ + unsigned char readback[2]; /* polled read-back values */ + + int mode; /* stk500 v2 xml file parameter */ + int delay; /* stk500 v2 xml file parameter */ + int blocksize; /* stk500 v2 xml file parameter */ + int readsize; /* stk500 v2 xml file parameter */ + int pollindex; /* stk500 v2 xml file parameter */ + + unsigned char * buf; /* pointer to memory buffer */ + OPCODE * op[AVR_OP_MAX]; /* opcodes */ +} AVRMEM; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for OPCODE structures */ +OPCODE * avr_new_opcode(void); +int avr_set_bits(OPCODE * op, unsigned char * cmd); +int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr); +int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data); +int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data); + +/* Functions for AVRMEM structures */ +AVRMEM * avr_new_memtype(void); +int avr_initmem(AVRPART * p); +AVRMEM * avr_dup_mem(AVRMEM * m); +AVRMEM * avr_locate_mem(AVRPART * p, char * desc); +void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type, + int verbose); + +/* Functions for AVRPART structures */ +AVRPART * avr_new_part(void); +AVRPART * avr_dup_part(AVRPART * d); +AVRPART * locate_part(LISTID parts, char * partdesc); +AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode); +void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose); + +typedef void (*walk_avrparts_cb)(const char *name, const char *desc, + const char *cfgname, int cfglineno, + void *cookie); +void walk_avrparts(LISTID programmers, walk_avrparts_cb cb, void *cookie); + +#ifdef __cplusplus +} +#endif + +#endif /* avrpart_h */ diff --git a/avrdude/bitbang.c b/avrdude/bitbang.c new file mode 100644 index 00000000..ada885ac --- /dev/null +++ b/avrdude/bitbang.c @@ -0,0 +1,660 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean + * Copyright (C) 2005 Michael Holzt + * Copyright (C) 2011 Darell Tan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#if !defined(WIN32NATIVE) +# include +# include +#endif + +#include "avrdude.h" +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" +#include "par.h" +#include "serbb.h" +#include "tpi.h" + +static int delay_decrement; + +#if defined(WIN32NATIVE) +static int has_perfcount; +static LARGE_INTEGER freq; +#else +static volatile int done; + +typedef void (*mysighandler_t)(int); +static mysighandler_t saved_alarmhandler; + +static void alarmhandler(int signo) +{ + done = 1; + signal(SIGALRM, saved_alarmhandler); +} +#endif /* WIN32NATIVE */ + +/* + * Calibrate the microsecond delay loop below. + */ +static void bitbang_calibrate_delay(void) +{ +#if defined(WIN32NATIVE) + /* + * If the hardware supports a high-resolution performance counter, + * we ultimately prefer that one, as it gives quite accurate delays + * on modern high-speed CPUs. + */ + if (QueryPerformanceFrequency(&freq)) + { + has_perfcount = 1; + if (verbose >= 2) + fprintf(stderr, + "%s: Using performance counter for bitbang delays\n", + progname); + } + else + { + /* + * If a high-resolution performance counter is not available, we + * don't have any Win32 implementation for setting up the + * per-microsecond delay count, so we can only run on a + * preconfigured delay stepping there. The figure below should at + * least be correct within an order of magnitude, judging from the + * auto-calibration figures seen on various Unix systems on + * comparable hardware. + */ + if (verbose >= 2) + fprintf(stderr, + "%s: Using guessed per-microsecond delay count for bitbang delays\n", + progname); + delay_decrement = 100; + } +#else /* !WIN32NATIVE */ + struct itimerval itv; + volatile int i; + + if (verbose >= 2) + fprintf(stderr, + "%s: Calibrating delay loop...", + progname); + i = 0; + done = 0; + saved_alarmhandler = signal(SIGALRM, alarmhandler); + /* + * Set ITIMER_REAL to 100 ms. All known systems have a timer + * granularity of 10 ms or better, so counting the delay cycles + * accumulating over 100 ms should give us a rather realistic + * picture, without annoying the user by a lengthy startup time (as + * an alarm(1) would do). Of course, if heavy system activity + * happens just during calibration but stops before the remaining + * part of AVRDUDE runs, this will yield wrong values. There's not + * much we can do about this. + */ + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 100000; + itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0; + setitimer(ITIMER_REAL, &itv, 0); + while (!done) + i--; + itv.it_value.tv_sec = itv.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &itv, 0); + /* + * Calculate back from 100 ms to 1 us. + */ + delay_decrement = -i / 100000; + if (verbose >= 2) + fprintf(stderr, + " calibrated to %d cycles per us\n", + delay_decrement); +#endif /* WIN32NATIVE */ +} + +/* + * Delay for approximately the number of microseconds specified. + * usleep()'s granularity is usually like 1 ms or 10 ms, so it's not + * really suitable for short delays in bit-bang algorithms. + */ +void bitbang_delay(int us) +{ +#if defined(WIN32NATIVE) + LARGE_INTEGER countNow, countEnd; + + if (has_perfcount) + { + QueryPerformanceCounter(&countNow); + countEnd.QuadPart = countNow.QuadPart + freq.QuadPart * us / 1000000ll; + + while (countNow.QuadPart < countEnd.QuadPart) + QueryPerformanceCounter(&countNow); + } + else /* no performance counters -- run normal uncalibrated delay */ + { +#endif /* WIN32NATIVE */ + volatile int del = us * delay_decrement; + + while (del > 0) + del--; +#if defined(WIN32NATIVE) + } +#endif /* WIN32NATIVE */ +} + +/* + * transmit and receive a byte of data to/from the AVR device + */ +static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte) +{ + int i; + unsigned char r, b, rbyte; + + rbyte = 0; + for (i=7; i>=0; i--) { + /* + * Write and read one bit on SPI. + * Some notes on timing: Let T be the time it takes to do + * one pgm->setpin()-call resp. par clrpin()-call, then + * - SCK is high for 2T + * - SCK is low for 2T + * - MOSI setuptime is 1T + * - MOSI holdtime is 3T + * - SCK low to MISO read is 2T to 3T + * So we are within programming specs (expect for AT90S1200), + * if and only if T>t_CLCL (t_CLCL=clock period of target system). + * + * Due to the delay introduced by "IN" and "OUT"-commands, + * T is greater than 1us (more like 2us) on x86-architectures. + * So programming works safely down to 1MHz target clock. + */ + + b = (byte >> i) & 0x01; + + /* set the data input line as desired */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], b); + + pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 1); + + /* + * read the result bit (it is either valid from a previous falling + * edge or it is ignored in the current context) + */ + r = pgm->getpin(pgm, pgm->pinno[PIN_AVR_MISO]); + + pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0); + + rbyte |= r << i; + } + + return rbyte; +} + +static int bitbang_tpi_clk(PROGRAMMER * pgm) +{ + unsigned char r = 0; + pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 1); + + r = pgm->getpin(pgm, pgm->pinno[PIN_AVR_MISO]); + + pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0); + + return r; +} + +void bitbang_tpi_tx(PROGRAMMER * pgm, unsigned char byte) +{ + int i; + unsigned char b, parity; + + /* start bit */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], 0); + bitbang_tpi_clk(pgm); + + parity = 0; + for (i = 0; i <= 7; i++) { + b = (byte >> i) & 0x01; + parity ^= b; + + /* set the data input line as desired */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], b); + bitbang_tpi_clk(pgm); + } + + /* parity bit */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], parity); + bitbang_tpi_clk(pgm); + + /* 2 stop bits */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], 1); + bitbang_tpi_clk(pgm); + bitbang_tpi_clk(pgm); +} + +int bitbang_tpi_rx(PROGRAMMER * pgm) +{ + int i; + unsigned char b, rbyte, parity; + + /* make sure pin is on for "pullup" */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], 1); + + /* wait for start bit (up to 10 bits) */ + b = 1; + for (i = 0; i < 10; i++) { + b = bitbang_tpi_clk(pgm); + if (b == 0) + break; + } + if (b != 0) { + fprintf(stderr, "bitbang_tpi_rx: start bit not received correctly\n"); + return -1; + } + + rbyte = 0; + parity = 0; + for (i=0; i<=7; i++) { + b = bitbang_tpi_clk(pgm); + parity ^= b; + + rbyte |= b << i; + } + + /* parity bit */ + if (bitbang_tpi_clk(pgm) != parity) { + fprintf(stderr, "bitbang_tpi_rx: parity bit is wrong\n"); + return -1; + } + + /* 2 stop bits */ + b = 1; + b &= bitbang_tpi_clk(pgm); + b &= bitbang_tpi_clk(pgm); + if (b != 1) { + fprintf(stderr, "bitbang_tpi_rx: stop bits not received correctly\n"); + return -1; + } + + return rbyte; +} + +int bitbang_rdy_led(PROGRAMMER * pgm, int value) +{ + pgm->setpin(pgm, pgm->pinno[PIN_LED_RDY], !value); + return 0; +} + +int bitbang_err_led(PROGRAMMER * pgm, int value) +{ + pgm->setpin(pgm, pgm->pinno[PIN_LED_ERR], !value); + return 0; +} + +int bitbang_pgm_led(PROGRAMMER * pgm, int value) +{ + pgm->setpin(pgm, pgm->pinno[PIN_LED_PGM], !value); + return 0; +} + +int bitbang_vfy_led(PROGRAMMER * pgm, int value) +{ + pgm->setpin(pgm, pgm->pinno[PIN_LED_VFY], !value); + return 0; +} + + +/* + * transmit an AVR device command and return the results; 'cmd' and + * 'res' must point to at least a 4 byte data buffer + */ +int bitbang_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + int i; + + for (i=0; i<4; i++) { + res[i] = bitbang_txrx(pgm, cmd[i]); + } + + if(verbose >= 2) + { + fprintf(stderr, "bitbang_cmd(): [ "); + for(i = 0; i < 4; i++) + fprintf(stderr, "%02X ", cmd[i]); + fprintf(stderr, "] [ "); + for(i = 0; i < 4; i++) + { + fprintf(stderr, "%02X ", res[i]); + } + fprintf(stderr, "]\n"); + } + + return 0; +} + +int bitbang_cmd_tpi(PROGRAMMER * pgm, unsigned char cmd[], + int cmd_len, unsigned char res[], int res_len) +{ + int i, r; + + pgm->pgm_led(pgm, ON); + + for (i=0; i= 2) + { + fprintf(stderr, "bitbang_cmd_tpi(): [ "); + for(i = 0; i < cmd_len; i++) + fprintf(stderr, "%02X ", cmd[i]); + fprintf(stderr, "] [ "); + for(i = 0; i < res_len; i++) + { + fprintf(stderr, "%02X ", res[i]); + } + fprintf(stderr, "]\n"); + } + + pgm->pgm_led(pgm, OFF); + if (r == -1) + return -1; + return 0; +} + +/* + * transmit bytes via SPI and return the results; 'cmd' and + * 'res' must point to data buffers + */ +int bitbang_spi(PROGRAMMER * pgm, unsigned char cmd[], + unsigned char res[], int count) +{ + int i; + + pgm->setpin(pgm, pgm->pinno[PIN_LED_PGM], 0); + + for (i=0; isetpin(pgm, pgm->pinno[PIN_LED_PGM], 1); + + if(verbose >= 2) + { + fprintf(stderr, "bitbang_cmd(): [ "); + for(i = 0; i < count; i++) + fprintf(stderr, "%02X ", cmd[i]); + fprintf(stderr, "] [ "); + for(i = 0; i < count; i++) + { + fprintf(stderr, "%02X ", res[i]); + } + fprintf(stderr, "]\n"); + } + + return 0; +} + + +/* + * issue the 'chip erase' command to the AVR device + */ +int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + AVRMEM *mem; + + if (p->flags & AVRPART_HAS_TPI) { + pgm->pgm_led(pgm, ON); + + while (avr_tpi_poll_nvmbsy(pgm)); + + /* NVMCMD <- CHIP_ERASE */ + bitbang_tpi_tx(pgm, TPI_CMD_SOUT | TPI_SIO_ADDR(TPI_IOREG_NVMCMD)); + bitbang_tpi_tx(pgm, TPI_NVMCMD_CHIP_ERASE); /* CHIP_ERASE */ + + /* Set Pointer Register */ + mem = avr_locate_mem(p, "flash"); + if (mem == NULL) { + fprintf(stderr, "No flash memory to erase for part %s\n", + p->desc); + return -1; + } + bitbang_tpi_tx(pgm, TPI_CMD_SSTPR | 0); + bitbang_tpi_tx(pgm, (mem->offset & 0xFF) | 1); /* high byte */ + bitbang_tpi_tx(pgm, TPI_CMD_SSTPR | 1); + bitbang_tpi_tx(pgm, (mem->offset >> 8) & 0xFF); + + /* write dummy value to start erase */ + bitbang_tpi_tx(pgm, TPI_CMD_SST); + bitbang_tpi_tx(pgm, 0xFF); + + while (avr_tpi_poll_nvmbsy(pgm)); + + pgm->pgm_led(pgm, OFF); + + return 0; + } + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return 0; +} + +/* + * issue the 'program enable' command to the AVR device + */ +int bitbang_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + int i; + + if (p->flags & AVRPART_HAS_TPI) { + /* enable NVM programming */ + bitbang_tpi_tx(pgm, TPI_CMD_SKEY); + for (i = sizeof(tpi_skey) - 1; i >= 0; i--) + bitbang_tpi_tx(pgm, tpi_skey[i]); + + /* check NVMEN bit */ + bitbang_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPISR); + i = bitbang_tpi_rx(pgm); + return (i != -1 && (i & TPI_REG_TPISR_NVMEN)) ? 0 : -2; + } + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) { + fprintf(stderr, "program enable instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); + pgm->cmd(pgm, cmd, res); + + if (res[2] != cmd[1]) + return -2; + + return 0; +} + +/* + * initialize the AVR device and prepare it to accept commands + */ +int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + int rc; + int tries; + int i; + + bitbang_calibrate_delay(); + + pgm->powerup(pgm); + usleep(20000); + + /* TPIDATA is a single line, so MISO & MOSI should be connected */ + if (p->flags & AVRPART_HAS_TPI) { + /* make sure cmd_tpi() is defined */ + if (pgm->cmd_tpi == NULL) { + fprintf(stderr, "%s: Error: %s programmer does not support TPI\n", + progname, pgm->type); + return -1; + } + + /* bring RESET high first */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); + usleep(1000); + + if (verbose >= 2) + fprintf(stderr, "doing MOSI-MISO link check\n"); + + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], 0); + if (pgm->getpin(pgm, pgm->pinno[PIN_AVR_MISO]) != 0) { + fprintf(stderr, "MOSI->MISO 0 failed\n"); + return -1; + } + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], 1); + if (pgm->getpin(pgm, pgm->pinno[PIN_AVR_MISO]) != 1) { + fprintf(stderr, "MOSI->MISO 1 failed\n"); + return -1; + } + + if (verbose >= 2) + fprintf(stderr, "MOSI-MISO link present\n"); + } + + pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0); + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0); + usleep(20000); + + if (p->flags & AVRPART_HAS_TPI) { + /* keep TPIDATA high for 16 clock cycles */ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], 1); + for (i = 0; i < 16; i++) + pgm->highpulsepin(pgm, pgm->pinno[PIN_AVR_SCK]); + + /* remove extra guard timing bits */ + bitbang_tpi_tx(pgm, TPI_CMD_SSTCS | TPI_REG_TPIPCR); + bitbang_tpi_tx(pgm, 0x7); + + /* read TPI ident reg */ + bitbang_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPIIR); + rc = bitbang_tpi_rx(pgm); + if (rc != 0x80) { + fprintf(stderr, "TPIIR not correct\n"); + return -1; + } + } else { + pgm->highpulsepin(pgm, pgm->pinno[PIN_AVR_RESET]); + } + + usleep(20000); /* 20 ms XXX should be a per-chip parameter */ + + /* + * Enable programming mode. If we are programming an AT90S1200, we + * can only issue the command and hope it worked. If we are using + * one of the other chips, the chip will echo 0x53 when issuing the + * third byte of the command. In this case, try up to 32 times in + * order to possibly get back into sync with the chip if we are out + * of sync. + */ + if (strcmp(p->desc, "AT90S1200")==0) { + pgm->program_enable(pgm, p); + } + else { + tries = 0; + do { + rc = pgm->program_enable(pgm, p); + if ((rc == 0)||(rc == -1)) + break; + pgm->highpulsepin(pgm, pgm->pinno[p->retry_pulse/*PIN_AVR_SCK*/]); + tries++; + } while (tries < 65); + + /* + * can't sync with the device, maybe it's not attached? + */ + if (rc) { + fprintf(stderr, "%s: AVR device not responding\n", progname); + return -1; + } + } + + return 0; +} + +static void verify_pin_assigned(PROGRAMMER * pgm, int pin, char * desc) +{ + if (pgm->pinno[pin] == 0) { + fprintf(stderr, "%s: error: no pin has been assigned for %s\n", + progname, desc); + exit(1); + } +} + + +/* + * Verify all prerequisites for a bit-bang programmer are present. + */ +void bitbang_check_prerequisites(PROGRAMMER *pgm) +{ + + verify_pin_assigned(pgm, PIN_AVR_RESET, "AVR RESET"); + verify_pin_assigned(pgm, PIN_AVR_SCK, "AVR SCK"); + verify_pin_assigned(pgm, PIN_AVR_MISO, "AVR MISO"); + verify_pin_assigned(pgm, PIN_AVR_MOSI, "AVR MOSI"); + + if (pgm->cmd == NULL) { + fprintf(stderr, "%s: error: no cmd() method defined for bitbang programmer\n", + progname); + exit(1); + } +} diff --git a/avrdude/bitbang.h b/avrdude/bitbang.h new file mode 100644 index 00000000..20159009 --- /dev/null +++ b/avrdude/bitbang.h @@ -0,0 +1,59 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean + * Copyright (C) 2005 Michael Holzt + * Copyright (C) 2011 Darell Tan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* $Id$ */ + +#ifndef bitbang_h +#define bitbang_h + +#ifdef __cplusplus +extern "C" { +#endif + +int bitbang_setpin(int fd, int pin, int value); +int bitbang_getpin(int fd, int pin); +int bitbang_highpulsepin(int fd, int pin); +void bitbang_delay(unsigned int us); + +void bitbang_check_prerequisites(PROGRAMMER *pgm); + +int bitbang_rdy_led (PROGRAMMER * pgm, int value); +int bitbang_err_led (PROGRAMMER * pgm, int value); +int bitbang_pgm_led (PROGRAMMER * pgm, int value); +int bitbang_vfy_led (PROGRAMMER * pgm, int value); +int bitbang_cmd (PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]); +int bitbang_cmd_tpi (PROGRAMMER * pgm, unsigned char cmd[], + int cmd_len, unsigned char res[], int res_len); +int bitbang_spi (PROGRAMMER * pgm, unsigned char cmd[], + unsigned char res[], int count); +int bitbang_chip_erase (PROGRAMMER * pgm, AVRPART * p); +int bitbang_program_enable (PROGRAMMER * pgm, AVRPART * p); +void bitbang_powerup (PROGRAMMER * pgm); +void bitbang_powerdown (PROGRAMMER * pgm); +int bitbang_initialize (PROGRAMMER * pgm, AVRPART * p); +void bitbang_disable (PROGRAMMER * pgm); +void bitbang_enable (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/bootstrap b/avrdude/bootstrap new file mode 100755 index 00000000..9dd39f15 --- /dev/null +++ b/avrdude/bootstrap @@ -0,0 +1,19 @@ +#! /bin/sh + +: ${AUTOHEADER="autoheader${AC_VER}"} +: ${AUTOCONF="autoconf${AC_VER}"} +: ${ACLOCAL="aclocal${AM_VER}"} +: ${AUTOMAKE="automake${AM_VER}"} + +export ACLOCAL AUTOHEADER AUTOCONF AUTOMAKE + +# Bootstrap the build system. + +set -x + +rm -rf autom4te.cache + +${ACLOCAL} +${AUTOHEADER} +${AUTOCONF} +${AUTOMAKE} -a -c diff --git a/avrdude/buspirate.c b/avrdude/buspirate.c new file mode 100644 index 00000000..d2034aab --- /dev/null +++ b/avrdude/buspirate.c @@ -0,0 +1,795 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * + * avrdude support for The Bus Pirate - universal serial interface + * + * Copyright (C) 2009 Michal Ludvig + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * BusPirate AVR Chip + * --------- -------- + * GND <-> GND + * +5V <-> Vcc + * CS <-> RESET + * MOSI <-> MOSI + * MISO <-> MISO + * SCL/CLK <-> SCK + * + * Tested with BusPirate PTH, firmware version 2.1 programming ATmega328P + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#if defined(WIN32NATIVE) +# include /* for alloca() */ +#endif + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "serial.h" + +/* ====== Private data structure ====== */ +/* CS and AUX pin bitmasks in + * 0100wxyz - Configure peripherals command */ +#define BP_RESET_CS 0x01 +#define BP_RESET_AUX 0x02 +#define BP_RESET_AUX2 0x04 + +#define BP_FLAG_IN_BINMODE (1<<0) +#define BP_FLAG_XPARM_FORCE_ASCII (1<<1) +#define BP_FLAG_XPARM_RESET (1<<2) +#define BP_FLAG_XPARM_SPIFREQ (1<<3) + +struct pdata +{ + char hw_version[10]; + int fw_version; /* = 100*fw_major + fw_minor */ + int binmode_version; + int bin_spi_version; + int current_peripherals_config; + int spifreq; /* 0..7 - see buspirate manual for what freq each value means */ + int reset; /* See BP_RESET_* above */ +}; +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +/* Binary mode is available from firmware v2.7 on */ +#define FW_BINMODE_VER 207 + +/* ====== Feature checks ====== */ +static inline int +buspirate_has_aux2(struct programmer_t *pgm) +{ + return ((PDATA(pgm)->fw_version >= 300) && + strcmp(PDATA(pgm)->hw_version, "v1a") == 0); +} + +static inline int +buspirate_uses_ascii(struct programmer_t *pgm) +{ + return (pgm->flag & BP_FLAG_XPARM_FORCE_ASCII) || + (PDATA(pgm)->fw_version < FW_BINMODE_VER); +} + +/* ====== Serial talker functions - binmode ====== */ + +static void dump_mem(char *buf, size_t len) +{ + size_t i; + + for (i = 0; i 1) { + fprintf(stderr, "%s: buspirate_send_bin():\n", progname); + dump_mem(data, len); + } + + rc = serial_send(&pgm->fd, (unsigned char *)data, len); + + return rc; +} + +static int buspirate_recv_bin(struct programmer_t *pgm, char *buf, size_t len) +{ + int rc; + + rc = serial_recv(&pgm->fd, (unsigned char *)buf, len); + if (rc < 0) + return EOF; + if (verbose > 1) { + fprintf(stderr, "%s: buspirate_recv_bin():\n", progname); + dump_mem(buf, len); + } + + return len; +} + +static int buspirate_expect_bin(struct programmer_t *pgm, + char *send_data, size_t send_len, + char *expect_data, size_t expect_len) +{ + char *recv_buf = alloca(expect_len); + if (!pgm->flag & BP_FLAG_IN_BINMODE) { + fprintf(stderr, "BusPirate: Internal error: buspirate_send_bin() called from ascii mode"); + exit(1); + } + + buspirate_send_bin(pgm, send_data, send_len); + buspirate_recv_bin(pgm, recv_buf, expect_len); + if (memcmp(expect_data, recv_buf, expect_len) != 0) + return 0; + return 1; +} + +static int buspirate_expect_bin_byte(struct programmer_t *pgm, + char send_byte, char expect_byte) +{ + return buspirate_expect_bin(pgm, &send_byte, 1, &expect_byte, 1); +} + +/* ====== Serial talker functions - ascii mode ====== */ + +static int buspirate_getc(struct programmer_t *pgm) +{ + int rc; + unsigned char ch = 0; + + if (pgm->flag & BP_FLAG_IN_BINMODE) { + fprintf(stderr, "BusPirate: Internal error: buspirate_getc() called from binmode"); + exit(1); + } + + rc = serial_recv(&pgm->fd, &ch, 1); + if (rc < 0) + return EOF; + return ch; +} + +static char *buspirate_readline_noexit(struct programmer_t *pgm, char *buf, size_t len) +{ + char *buf_p; + long orig_serial_recv_timeout = serial_recv_timeout; + + /* Static local buffer - this may come handy at times */ + static char buf_local[100]; + + if (buf == NULL) { + buf = buf_local; + len = sizeof(buf_local); + } + buf_p = buf; + memset(buf, 0, len); + while (buf_p < (buf + len - 1)) { /* keep the very last byte == 0 */ + *buf_p = buspirate_getc(pgm); + if (*buf_p == '\r') + continue; + if (*buf_p == '\n') + break; + if (*buf_p == EOF) { + *buf_p = '\0'; + break; + } + buf_p++; + serial_recv_timeout = 100; + } + serial_recv_timeout = orig_serial_recv_timeout; + if (verbose) + fprintf(stderr, "%s: buspirate_readline(): %s%s", + progname, buf, + buf[strlen(buf) - 1] == '\n' ? "" : "\n"); + if (! buf[0]) + return NULL; + + return buf; +} + +static char *buspirate_readline(struct programmer_t *pgm, char *buf, size_t len) +{ + char *ret; + + ret = buspirate_readline_noexit(pgm, buf, len); + if (! ret) { + fprintf(stderr, + "%s: buspirate_readline(): programmer is not responding\n", + progname); + exit(1); + } + return ret; +} +static int buspirate_send(struct programmer_t *pgm, char *str) +{ + int rc; + + if (verbose) + fprintf(stderr, "%s: buspirate_send(): %s", progname, str); + + if (pgm->flag & BP_FLAG_IN_BINMODE) { + fprintf(stderr, "BusPirate: Internal error: buspirate_send() called from binmode"); + exit(1); + } + + rc = serial_send(&pgm->fd, (unsigned char *)str, strlen(str)); + if (rc) + return rc; + while (strcmp(buspirate_readline(pgm, NULL, 0), str) != 0) + /* keep reading until we get what we sent there */ + ; + /* by now we should be in sync */ + return 0; +} + +static int buspirate_is_prompt(char *str) +{ + /* Prompt ends with '>' or '> ' + * all other input probably ends with '\n' */ + return (str[strlen(str) - 1] == '>' || str[strlen(str) - 2] == '>'); +} + +static int buspirate_expect(struct programmer_t *pgm, char *send, + char *expect, int wait_for_prompt) +{ + int got_it = 0; + size_t expect_len = strlen(expect); + char *rcvd; + + buspirate_send(pgm, send); + while (1) { + rcvd = buspirate_readline(pgm, NULL, 0); + + if (strncmp(rcvd, expect, expect_len) == 0) + got_it = 1; + + if (buspirate_is_prompt(rcvd)) + break; + } + return got_it; +} + +/* ====== Do-nothing functions ====== */ +static void buspirate_dummy_6(struct programmer_t *pgm, + const char *p) +{ +} + +/* ====== Config / parameters handling functions ====== */ +static int +buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms) +{ + LNODEID ln; + const char *extended_param; + char reset[10]; + char *preset = reset; /* for strtok() */ + int spifreq; + + for (ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + if (strcmp(extended_param, "ascii") == 0) { + pgm->flag |= BP_FLAG_XPARM_FORCE_ASCII; + continue; + } + if (sscanf(extended_param, "spifreq=%d", &spifreq) == 1) { + if (spifreq & (~0x07)) { + fprintf(stderr, "BusPirate: spifreq must be between 0 and 7.\n"); + fprintf(stderr, "BusPirate: see BusPirate manual for details.\n"); + return -1; + } + PDATA(pgm)->spifreq = spifreq; + pgm->flag |= BP_FLAG_XPARM_SPIFREQ; + continue; + } + + if (sscanf(extended_param, "reset=%s", reset) == 1) { + char *resetpin; + while ((resetpin = strtok(preset, ","))) { + preset = NULL; /* for subsequent strtok() calls */ + if (strcasecmp(resetpin, "cs") == 0) + PDATA(pgm)->reset |= BP_RESET_CS; + else if (strcasecmp(resetpin, "aux") == 0 || strcasecmp(reset, "aux1") == 0) + PDATA(pgm)->reset |= BP_RESET_AUX; + else if (strcasecmp(resetpin, "aux2") == 0) + PDATA(pgm)->reset |= BP_RESET_AUX2; + else { + fprintf(stderr, "BusPirate: reset must be either CS or AUX.\n"); + return -1; + } + } + pgm->flag |= BP_FLAG_XPARM_RESET; + continue; + } + } + + return 0; +} + +static int +buspirate_verifyconfig(struct programmer_t *pgm) +{ + /* Default reset pin is CS */ + if (PDATA(pgm)->reset == 0x00) + PDATA(pgm)->reset |= BP_RESET_CS; + + /* reset=AUX2 is only available on HW=v1a and FW>=3.0 */ + if ((PDATA(pgm)->reset & BP_RESET_AUX2) && !buspirate_has_aux2(pgm)) { + fprintf(stderr, "BusPirate: Pin AUX2 is only available in binary mode\n"); + fprintf(stderr, "BusPirate: with hardware==v1a && firmware>=3.0\n"); + fprintf(stderr, "BusPirate: Your hardware==%s and firmware==%d.%d\n", + PDATA(pgm)->hw_version, PDATA(pgm)->fw_version/100, PDATA(pgm)->fw_version%100); + return -1; + } + + if ((PDATA(pgm)->reset != BP_RESET_CS) && buspirate_uses_ascii(pgm)) { + fprintf(stderr, "BusPirate: RESET pin other than CS is not supported in ASCII mode\n"); + return -1; + } + + if ((pgm->flag & BP_FLAG_XPARM_SPIFREQ) && buspirate_uses_ascii(pgm)) { + fprintf(stderr, "BusPirate: SPI speed selection is not supported in ASCII mode\n"); + return -1; + } + + return 0; +} + +/* ====== Programmer methods ======= */ +static int buspirate_open(struct programmer_t *pgm, char * port) +{ + /* BusPirate runs at 115200 by default */ + if(pgm->baudrate == 0) + pgm->baudrate = 115200; + + strcpy(pgm->port, port); + if (serial_open(port, pgm->baudrate, &pgm->fd)==-1) { + return -1; + } + + /* drain any extraneous input */ + serial_drain(&pgm->fd, 0); + + return 0; +} + +static void buspirate_close(struct programmer_t *pgm) +{ + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + +static void buspirate_reset_from_binmode(struct programmer_t *pgm) +{ + char buf[10]; + + buf[0] = 0x00; /* BinMode: revert to HiZ */ + buspirate_send_bin(pgm, buf, 1); + + buf[0] = 0x0F; /* BinMode: reset */ + buspirate_send_bin(pgm, buf, 1); + + /* read back all output */ + memset(buf, '\0', sizeof(buf)); + for (;;) { + int rc; + rc = buspirate_recv_bin(pgm, buf, sizeof(buf) - 1); + + if (buspirate_is_prompt(buf)) { + pgm->flag &= ~BP_FLAG_IN_BINMODE; + break; + } + if (rc == EOF) + break; + memset(buf, '\0', sizeof(buf)); + } + + if (pgm->flag & BP_FLAG_IN_BINMODE) { + fprintf(stderr, "BusPirate reset failed. You may need to powercycle it.\n"); + exit(1); + } + + if (verbose) + fprintf(stderr, "BusPirate is back in the text mode\n"); +} + +static int buspirate_start_spi_mode_bin(struct programmer_t *pgm) +{ + char buf[20] = { '\0' }; + + /* == Switch to binmode - send 20x '\0' == */ + buspirate_send_bin(pgm, buf, sizeof(buf)); + + /* Expecting 'BBIOx' reply */ + memset(buf, 0, sizeof(buf)); + buspirate_recv_bin(pgm, buf, 5); + if (sscanf(buf, "BBIO%d", &PDATA(pgm)->binmode_version) != 1) { + fprintf(stderr, "Binary mode not confirmed: '%s'\n", buf); + buspirate_reset_from_binmode(pgm); + return -1; + } + if (verbose) + fprintf(stderr, "BusPirate binmode version: %d\n", + PDATA(pgm)->binmode_version); + + pgm->flag |= BP_FLAG_IN_BINMODE; + + /* == Enter SPI mode == */ + buf[0] = 0x01; /* Enter raw SPI mode */ + buspirate_send_bin(pgm, buf, 1); + memset(buf, 0, sizeof(buf)); + buspirate_recv_bin(pgm, buf, 4); + if (sscanf(buf, "SPI%d", &PDATA(pgm)->bin_spi_version) != 1) { + fprintf(stderr, "SPI mode not confirmed: '%s'\n", buf); + buspirate_reset_from_binmode(pgm); + return -1; + } + if (verbose) + fprintf(stderr, "BusPirate SPI version: %d\n", + PDATA(pgm)->bin_spi_version); + + /* 0b0100wxyz - Configure peripherals w=power, x=pull-ups/aux2, y=AUX, z=CS + * we want power (0x48) and all reset pins high. */ + PDATA(pgm)->current_peripherals_config = 0x48; + PDATA(pgm)->current_peripherals_config |= BP_RESET_CS; + PDATA(pgm)->current_peripherals_config |= BP_RESET_AUX; + if (buspirate_has_aux2(pgm)) + PDATA(pgm)->current_peripherals_config |= BP_RESET_AUX2; + buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01); + usleep(50000); // sleep for 50ms after power up + + /* 01100xxx - SPI speed + * xxx = 000=30kHz, 001=125kHz, 010=250kHz, 011=1MHz, + * 100=2MHz, 101=2.6MHz, 110=4MHz, 111=8MHz + * use 30kHz = 0x60 */ + buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01); + + /* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample + * we want: 3.3V(1), idle low(0), data change on trailing edge (1), + * sample in the middle of the pulse (0) + * => 0b10001010 = 0x8a */ + buspirate_expect_bin_byte(pgm, 0x8A, 0x01); + + return 0; +} + +static int buspirate_start_spi_mode_ascii(struct programmer_t *pgm) +{ + int spi_cmd = -1; + int cmd; + char *rcvd, mode[11], buf[5]; + + buspirate_send(pgm, "M\n"); + while(1) { + rcvd = buspirate_readline(pgm, NULL, 0); + if (spi_cmd == -1 && sscanf(rcvd, "%d. %10s", &cmd, mode)) { + if (strcmp(mode, "SPI") == 0) + spi_cmd = cmd; + } + if (buspirate_is_prompt(rcvd)) + break; + } + if (spi_cmd == -1) { + fprintf(stderr, + "%s: SPI mode number not found. Does your BusPirate support SPI?\n", + progname); + fprintf(stderr, "%s: Try powercycling your BusPirate and try again.\n", + progname); + return -1; + } + snprintf(buf, sizeof(buf), "%d\n", spi_cmd); + buspirate_send(pgm, buf); + buf[0] = '\0'; + while (1) { + rcvd = buspirate_readline(pgm, NULL, 0); + if (strstr(rcvd, "Normal (H=3.3V, L=GND)")) { + /* BP firmware 2.1 defaults to Open-drain output. + * That doesn't work on my board, even with pull-up + * resistors. Select 3.3V output mode instead. */ + sscanf(rcvd, " %d.", &cmd); + snprintf(buf, sizeof(buf), "%d\n", cmd); + } + if (buspirate_is_prompt(rcvd)) { + if (strncmp(rcvd, "SPI>", 4) == 0) { + fprintf(stderr, "BusPirate is now configured for SPI\n"); + break; + } + /* Not yet 'SPI>' prompt */ + if (buf[0]) { + buspirate_send(pgm, buf); + buf[0] = '\0'; + } else + buspirate_send(pgm, "\n"); + } + } + return 0; +} + +static void buspirate_enable(struct programmer_t *pgm) +{ + unsigned char *reset_str = "#\n"; + unsigned char *accept_str = "y\n"; + char *rcvd; + int fw_v1 = 0, fw_v2 = 0; + int rc, print_banner = 0; + + fprintf(stderr, "Detecting BusPirate...\n"); + + /* Call buspirate_send_bin() instead of buspirate_send() + * because we don't know if BP is in text or bin mode */ + rc = buspirate_send_bin(pgm, reset_str, strlen(reset_str)); + if (rc) { + fprintf(stderr, "BusPirate is not responding. Serial port error: %d\n", rc); + exit(1); + } + + while(1) { + rcvd = buspirate_readline_noexit(pgm, NULL, 0); + if (! rcvd) { + fprintf(stderr, "BusPirate is not responding. Attempting reset.\n"); + buspirate_reset_from_binmode(pgm); + /* re-run buspirate_enable() */ + buspirate_enable(pgm); + return; + } + if (strncmp(rcvd, "Are you sure?", 13) == 0) { + buspirate_send_bin(pgm, accept_str, strlen(accept_str)); + } + if (strncmp(rcvd, "RESET", 5) == 0) { + print_banner = 1; + continue; + } + if (buspirate_is_prompt(rcvd)) { + puts("**"); + break; + } + sscanf(rcvd, "Bus Pirate %9s", PDATA(pgm)->hw_version); + sscanf(rcvd, "Firmware v%d.%d", &fw_v1, &fw_v2); + if (print_banner) + fprintf(stderr, "** %s", rcvd); + } + + PDATA(pgm)->fw_version = 100 * fw_v1 + fw_v2; + if (PDATA(pgm)->hw_version[0] == 0 || PDATA(pgm)->fw_version == 0) { + fprintf(stderr, "BusPirate not detected. Aborting.\n"); + exit(1); + } + + if (buspirate_verifyconfig(pgm) < 0) + exit(1); + + if (PDATA(pgm)->fw_version >= FW_BINMODE_VER && !(pgm->flag & BP_FLAG_XPARM_FORCE_ASCII)) { + fprintf(stderr, "BusPirate: using BINARY mode\n"); + if (buspirate_start_spi_mode_bin(pgm) < 0) + fprintf(stderr, "%s: Failed to start binary SPI mode\n", progname); + } + if (!pgm->flag & BP_FLAG_IN_BINMODE) { + fprintf(stderr, "BusPirate: using ASCII mode\n"); + if (buspirate_start_spi_mode_ascii(pgm) < 0) { + fprintf(stderr, "%s: Failed to start ascii SPI mode\n", progname); + exit(1); + } + } +} + +static void buspirate_disable(struct programmer_t *pgm) +{ + if (pgm->flag & BP_FLAG_IN_BINMODE) { + serial_recv_timeout = 100; + buspirate_reset_from_binmode(pgm); + } else + buspirate_expect(pgm, "#\n", "RESET", 1); +} + +static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p) +{ + pgm->powerup(pgm); + + return pgm->program_enable(pgm, p); +} + +static void buspirate_powerup(struct programmer_t *pgm) +{ + if (pgm->flag & BP_FLAG_IN_BINMODE) { + /* Powerup in BinMode is handled in SPI init */ + return; + } else + if (buspirate_expect(pgm, "W\n", "POWER SUPPLIES ON", 1)) + return; + + fprintf(stderr, "%s: warning: did not get a response to PowerUp command.\n", progname); + fprintf(stderr, "%s: warning: Trying to continue anyway...\n", progname); +} + +static void buspirate_powerdown(struct programmer_t *pgm) +{ + if (pgm->flag & BP_FLAG_IN_BINMODE) { + /* 0b0100wxyz - Configure peripherals w=power, x=pull-ups, y=AUX, z=CS + * we want everything off -- 0b01000000 = 0x40 */ + if (buspirate_expect_bin_byte(pgm, 0x40, 0x01)) + return; + } else + if (buspirate_expect(pgm, "w\n", "POWER SUPPLIES OFF", 1)) + return; + + fprintf(stderr, "%s: warning: did not get a response to PowerDown command.\n", progname); +} + +static int buspirate_cmd_bin(struct programmer_t *pgm, + unsigned char cmd[4], + unsigned char res[4]) +{ + /* 0001xxxx - Bulk SPI transfer, send/read 1-16 bytes (0=1byte!) + * we are sending 4 bytes -> 0x13 */ + if (!buspirate_expect_bin_byte(pgm, 0x13, 0x01)) + return -1; + + buspirate_send_bin(pgm, (char *)cmd, 4); + buspirate_recv_bin(pgm, (char *)res, 4); + + return 0; +} + +static int buspirate_cmd_ascii(struct programmer_t *pgm, + unsigned char cmd[4], + unsigned char res[4]) +{ + char buf[25]; + char *rcvd; + int spi_write, spi_read, i = 0; + + snprintf(buf, sizeof(buf), "0x%02x 0x%02x 0x%02x 0x%02x\n", + cmd[0], cmd[1], cmd[2], cmd[3]); + buspirate_send(pgm, buf); + while (i < 4) { + rcvd = buspirate_readline(pgm, NULL, 0); + /* WRITE: 0xAC READ: 0x04 */ + if (sscanf(rcvd, "WRITE: 0x%x READ: 0x%x", &spi_write, &spi_read) == 2) { + res[i++] = spi_read; + } + if (buspirate_is_prompt(rcvd)) + break; + } + + if (i != 4) { + fprintf(stderr, "%s: error: SPI has not read 4 bytes back\n", progname); + return -1; + } + + /* wait for prompt */ + while (buspirate_getc(pgm) != '>') + /* do nothing */; + + return 0; +} + +static int buspirate_cmd(struct programmer_t *pgm, + unsigned char cmd[4], + unsigned char res[4]) +{ + if (pgm->flag & BP_FLAG_IN_BINMODE) + return buspirate_cmd_bin(pgm, cmd, res); + else + return buspirate_cmd_ascii(pgm, cmd, res); +} + +static int buspirate_program_enable(struct programmer_t *pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + if (pgm->flag & BP_FLAG_IN_BINMODE) { + /* Clear configured reset pin(s): CS and/or AUX and/or AUX2 */ + PDATA(pgm)->current_peripherals_config &= ~PDATA(pgm)->reset; + buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01); + } + else + buspirate_expect(pgm, "{\n", "CS ENABLED", 1); + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) { + fprintf(stderr, + "program enable instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); + pgm->cmd(pgm, cmd, res); + + if (res[2] != cmd[1]) + return -2; + + return 0; +} + +static int buspirate_chip_erase(struct programmer_t *pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, + "chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return 0; +} + +void buspirate_initpgm(struct programmer_t *pgm) +{ + strcpy(pgm->type, "BusPirate"); + + pgm->display = buspirate_dummy_6; + + /* BusPirate itself related methods */ + pgm->open = buspirate_open; + pgm->close = buspirate_close; + pgm->enable = buspirate_enable; + pgm->disable = buspirate_disable; + pgm->initialize = buspirate_initialize; + + /* Chip related methods */ + pgm->powerup = buspirate_powerup; + pgm->powerdown = buspirate_powerdown; + pgm->program_enable = buspirate_program_enable; + pgm->chip_erase = buspirate_chip_erase; + pgm->cmd = buspirate_cmd; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* Support functions */ + pgm->parseextparams = buspirate_parseextparms; + + /* Allocate private data */ + if ((pgm->cookie = calloc(1, sizeof(struct pdata))) == 0) { + fprintf(stderr, "%s: buspirate_initpgm(): Out of memory allocating private data\n", + progname); + exit(1); + } +} + diff --git a/avrdude/buspirate.h b/avrdude/buspirate.h new file mode 100644 index 00000000..a0d6095f --- /dev/null +++ b/avrdude/buspirate.h @@ -0,0 +1,30 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * + * avrdude support for The Bus Pirate - universal serial interface + * + * Copyright (C) 2009 Michal Ludvig + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef buspirate_h +#define buspirate_h + +void buspirate_initpgm (struct programmer_t *pgm); + +#endif diff --git a/avrdude/butterfly.c b/avrdude/butterfly.c new file mode 100644 index 00000000..bb7c35c9 --- /dev/null +++ b/avrdude/butterfly.c @@ -0,0 +1,747 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * Copyright (C) 2005, 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for the serial programming mode of the Atmel butterfly + * evaluation board. This board features a bootloader which uses a protocol + * very similar, but not identical, to the one described in application note + * avr910. + * + * Actually, the butterfly uses a predecessor of the avr910 protocol + * which is described in application notes avr109 (generic AVR + * bootloader) and avr911 (opensource programmer). This file now + * fully handles the features present in avr109. It should probably + * be renamed to avr109, but we rather stick with the old name inside + * the file. We'll provide aliases for "avr109" and "avr911" in + * avrdude.conf so users could call it by these name as well. + */ + + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "butterfly.h" +#include "serial.h" + +/* + * Private data for this programmer. + */ +struct pdata +{ + char has_auto_incr_addr; + unsigned int buffersize; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +static void butterfly_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: butterfly_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void butterfly_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + +static int butterfly_send(PROGRAMMER * pgm, char * buf, size_t len) +{ + return serial_send(&pgm->fd, (unsigned char *)buf, len); +} + + +static int butterfly_recv(PROGRAMMER * pgm, char * buf, size_t len) +{ + int rv; + + rv = serial_recv(&pgm->fd, (unsigned char *)buf, len); + if (rv < 0) { + fprintf(stderr, + "%s: butterfly_recv(): programmer is not responding\n", + progname); + exit(1); + } + return 0; +} + + +static int butterfly_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(&pgm->fd, display); +} + + +static void butterfly_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg) +{ + char c; + + butterfly_recv(pgm, &c, 1); + if (c != '\r') { + fprintf(stderr, "%s: error: programmer did not respond to command: %s\n", + progname, errmsg); + exit(1); + } +} + + +static int butterfly_rdy_led(PROGRAMMER * pgm, int value) +{ + /* Do nothing. */ + + return 0; +} + + +static int butterfly_err_led(PROGRAMMER * pgm, int value) +{ + /* Do nothing. */ + + return 0; +} + + +static int butterfly_pgm_led(PROGRAMMER * pgm, int value) +{ + /* Do nothing. */ + + return 0; +} + + +static int butterfly_vfy_led(PROGRAMMER * pgm, int value) +{ + /* Do nothing. */ + + return 0; +} + + +/* + * issue the 'chip erase' command to the butterfly board + */ +static int butterfly_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + butterfly_send(pgm, "e", 1); + butterfly_vfy_cmd_sent(pgm, "chip erase"); + + return 0; +} + + +static void butterfly_enter_prog_mode(PROGRAMMER * pgm) +{ + butterfly_send(pgm, "P", 1); + butterfly_vfy_cmd_sent(pgm, "enter prog mode"); +} + + +static void butterfly_leave_prog_mode(PROGRAMMER * pgm) +{ + butterfly_send(pgm, "L", 1); + butterfly_vfy_cmd_sent(pgm, "leave prog mode"); +} + + +/* + * issue the 'program enable' command to the AVR device + */ +static int butterfly_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + return -1; +} + + +/* + * apply power to the AVR processor + */ +static void butterfly_powerup(PROGRAMMER * pgm) +{ + /* Do nothing. */ + + return; +} + + +/* + * remove power from the AVR processor + */ +static void butterfly_powerdown(PROGRAMMER * pgm) +{ + /* Do nothing. */ + + return; +} + +#define IS_BUTTERFLY_MK 0x0001 + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + char id[8]; + char sw[2]; + char hw[2]; + char buf[10]; + char type; + char c, devtype_1st; + + /* + * Send some ESC to activate butterfly bootloader. This is not needed + * for plain avr109 bootloaders but does not harm there either. + */ + fprintf(stderr, "Connecting to programmer: "); + if (pgm->flag & IS_BUTTERFLY_MK) + { + char mk_reset_cmd[6] = {"#aR@S\r"}; + unsigned char mk_timeout = 0; + + putc('.', stderr); + butterfly_send(pgm, mk_reset_cmd, sizeof(mk_reset_cmd)); + usleep(20000); + + do + { + c = 27; + butterfly_send(pgm, &c, 1); + usleep(20000); + c = 0xaa; + usleep(80000); + butterfly_send(pgm, &c, 1); + if (mk_timeout % 10 == 0) putc('.', stderr); + } while (mk_timeout++ < 10); + + butterfly_recv(pgm, &c, 1); + if ( c != 'M' && c != '?') + { + fprintf(stderr, "\nConnection FAILED."); + exit(1); + } + else + { + id[0] = 'M'; id[1] = 'K'; id[2] = '2'; id[3] = 0; + } + } + else + { + do { + putc('.', stderr); + butterfly_send(pgm, "\033", 1); + butterfly_drain(pgm, 0); + butterfly_send(pgm, "S", 1); + butterfly_recv(pgm, &c, 1); + if (c != '?') { + putc('\n', stderr); + /* + * Got a useful response, continue getting the programmer + * identifier. Programmer returns exactly 7 chars _without_ + * the null. + */ + id[0] = c; + butterfly_recv(pgm, &id[1], sizeof(id)-2); + id[sizeof(id)-1] = '\0'; + } + } while (c == '?'); + } + + /* Get the HW and SW versions to see if the programmer is present. */ + butterfly_drain(pgm, 0); + + butterfly_send(pgm, "V", 1); + butterfly_recv(pgm, sw, sizeof(sw)); + + butterfly_send(pgm, "v", 1); + butterfly_recv(pgm, hw, 1); /* first, read only _one_ byte */ + if (hw[0]!='?') { + butterfly_recv(pgm, &hw[1], 1);/* now, read second byte */ + }; + + /* Get the programmer type (serial or parallel). Expect serial. */ + + butterfly_send(pgm, "p", 1); + butterfly_recv(pgm, &type, 1); + + fprintf(stderr, "Found programmer: Id = \"%s\"; type = %c\n", id, type); + fprintf(stderr, " Software Version = %c.%c; ", sw[0], sw[1]); + if (hw[0]=='?') { + fprintf(stderr, "No Hardware Version given.\n"); + } else { + fprintf(stderr, "Hardware Version = %c.%c\n", hw[0], hw[1]); + }; + + /* See if programmer supports autoincrement of address. */ + + butterfly_send(pgm, "a", 1); + butterfly_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1); + if (PDATA(pgm)->has_auto_incr_addr == 'Y') + fprintf(stderr, "Programmer supports auto addr increment.\n"); + + /* Check support for buffered memory access, abort if not available */ + + butterfly_send(pgm, "b", 1); + butterfly_recv(pgm, &c, 1); + if (c != 'Y') { + fprintf(stderr, + "%s: error: buffered memory access not supported. Maybe it isn't\n"\ + "a butterfly/AVR109 but a AVR910 device?\n", progname); + exit(1); + }; + butterfly_recv(pgm, &c, 1); + PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8; + butterfly_recv(pgm, &c, 1); + PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c; + fprintf(stderr, + "Programmer supports buffered memory access with buffersize=%i bytes.\n", + PDATA(pgm)->buffersize); + + /* Get list of devices that the programmer supports. */ + + butterfly_send(pgm, "t", 1); + fprintf(stderr, "\nProgrammer supports the following devices:\n"); + devtype_1st = 0; + while (1) { + butterfly_recv(pgm, &c, 1); + if (devtype_1st == 0) + devtype_1st = c; + + if (c == 0) + break; + fprintf(stderr, " Device code: 0x%02x\n", (unsigned int)(unsigned char)c); + }; + fprintf(stderr,"\n"); + + /* Tell the programmer which part we selected. + According to the AVR109 code, this is ignored by the bootloader. As + some early versions might not properly ignore it, rather pick up the + first device type as reported above than anything out of avrdude.conf, + so to avoid a potential conflict. There appears to be no general + agreement on AVR910 device IDs beyond the ones from the original + appnote 910. */ + + buf[0] = 'T'; + buf[1] = devtype_1st; + + butterfly_send(pgm, buf, 2); + butterfly_vfy_cmd_sent(pgm, "select device"); + + if (verbose) + fprintf(stderr, + "%s: devcode selected: 0x%02x\n", + progname, (unsigned)buf[1]); + + butterfly_enter_prog_mode(pgm); + butterfly_drain(pgm, 0); + + return 0; +} + + + +static void butterfly_disable(PROGRAMMER * pgm) +{ + butterfly_leave_prog_mode(pgm); + + return; +} + + +static void butterfly_enable(PROGRAMMER * pgm) +{ + return; +} + + +static int butterfly_open(PROGRAMMER * pgm, char * port) +{ + strcpy(pgm->port, port); + /* + * If baudrate was not specified use 19200 Baud + */ + if(pgm->baudrate == 0) { + pgm->baudrate = 19200; + } + if (serial_open(port, pgm->baudrate, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + butterfly_drain (pgm, 0); + + return 0; +} + + +static void butterfly_close(PROGRAMMER * pgm) +{ + /* "exit programmer" */ + butterfly_send(pgm, "E", 1); + butterfly_vfy_cmd_sent(pgm, "exit bootloader"); + + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + + +static void butterfly_display(PROGRAMMER * pgm, const char * p) +{ + return; +} + + +static void butterfly_set_addr(PROGRAMMER * pgm, unsigned long addr) +{ + char cmd[3]; + + cmd[0] = 'A'; + cmd[1] = (addr >> 8) & 0xff; + cmd[2] = addr & 0xff; + + butterfly_send(pgm, cmd, sizeof(cmd)); + butterfly_vfy_cmd_sent(pgm, "set addr"); +} + + +static void butterfly_set_extaddr(PROGRAMMER * pgm, unsigned long addr) +{ + char cmd[4]; + + cmd[0] = 'H'; + cmd[1] = (addr >> 16) & 0xff; + cmd[2] = (addr >> 8) & 0xff; + cmd[3] = addr & 0xff; + + butterfly_send(pgm, cmd, sizeof(cmd)); + butterfly_vfy_cmd_sent(pgm, "set extaddr"); +} + + + +static int butterfly_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char value) +{ + char cmd[6]; + int size; + int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; + + if ((strcmp(m->desc, "flash") == 0) || (strcmp(m->desc, "eeprom") == 0)) + { + cmd[0] = 'B'; + cmd[1] = 0; + if ((cmd[3] = toupper((int)(m->desc[0]))) == 'E') { /* write to eeprom */ + cmd[2] = 1; + cmd[4] = value; + size = 5; + } else { /* write to flash */ + /* @@@ not yet implemented */ + cmd[2] = 2; + size = 6; + return -1; + } + if (use_ext_addr) { + butterfly_set_extaddr(pgm, addr); + } else { + butterfly_set_addr(pgm, addr); + } + } + else if (strcmp(m->desc, "lock") == 0) + { + cmd[0] = 'l'; + cmd[1] = value; + size = 2; + } + else + return -1; + + butterfly_send(pgm, cmd, size); + butterfly_vfy_cmd_sent(pgm, "write byte"); + + return 0; +} + + +static int butterfly_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value) +{ + static int cached = 0; + static unsigned char cvalue; + static unsigned long caddr; + int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; + + if (cached && ((caddr + 1) == addr)) { + *value = cvalue; + cached = 0; + } + else { + char buf[2]; + + if (use_ext_addr) { + butterfly_set_extaddr(pgm, addr >> 1); + } else { + butterfly_set_addr(pgm, addr >> 1); + } + + butterfly_send(pgm, "g\000\002F", 4); + + /* Read back the program mem word (MSB first) */ + butterfly_recv(pgm, buf, sizeof(buf)); + + if ((addr & 0x01) == 0) { + *value = buf[1]; + cached = 1; + cvalue = buf[0]; + caddr = addr; + } + else { + *value = buf[0]; + } + } + + return 0; +} + + +static int butterfly_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value) +{ + butterfly_set_addr(pgm, addr); + butterfly_send(pgm, "g\000\001E", 4); + butterfly_recv(pgm, (char *)value, 1); + return 0; +} + + +static int butterfly_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value) +{ + char cmd; + + if (strcmp(m->desc, "flash") == 0) { + return butterfly_read_byte_flash(pgm, p, m, addr, value); + } + + if (strcmp(m->desc, "eeprom") == 0) { + return butterfly_read_byte_eeprom(pgm, p, m, addr, value); + } + + if (strcmp(m->desc, "lfuse") == 0) { + cmd = 'F'; + } + else if (strcmp(m->desc, "hfuse") == 0) { + cmd = 'N'; + } + else if (strcmp(m->desc, "efuse") == 0) { + cmd = 'Q'; + } + else if (strcmp(m->desc, "lock") == 0) { + cmd = 'r'; + } + else + return -1; + + butterfly_send(pgm, &cmd, 1); + butterfly_recv(pgm, (char *)value, 1); + + return *value == '?'? -1: 0; +} + + + +static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + char *cmd; + unsigned int blocksize = PDATA(pgm)->buffersize; + int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; + + if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) + return -2; + + if (m->desc[0] == 'e') + blocksize = 1; /* Write to eeprom single bytes only */ + + if (use_ext_addr) { + butterfly_set_extaddr(pgm, addr); + } else { + butterfly_set_addr(pgm, addr); + } + +#if 0 + usleep(1000000); + butterfly_send(pgm, "y", 1); + butterfly_vfy_cmd_sent(pgm, "clear LED"); +#endif + + cmd = malloc(4+blocksize); + if (!cmd) return -1; + cmd[0] = 'B'; + cmd[3] = toupper((int)(m->desc[0])); + + while (addr < max_addr) { + if ((max_addr - addr) < blocksize) { + blocksize = max_addr - addr; + }; + memcpy(&cmd[4], &m->buf[addr], blocksize); + cmd[1] = (blocksize >> 8) & 0xff; + cmd[2] = blocksize & 0xff; + + butterfly_send(pgm, cmd, 4+blocksize); + butterfly_vfy_cmd_sent(pgm, "write block"); + + addr += blocksize; + + report_progress (addr, max_addr, NULL); + } /* while */ + free(cmd); + + return addr; +} + + + +static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + int rd_size = 1; + int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; + + /* check parameter syntax: only "flash" or "eeprom" is allowed */ + if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) + return -2; + + { /* use buffered mode */ + char cmd[4]; + int blocksize = PDATA(pgm)->buffersize; + + cmd[0] = 'g'; + cmd[3] = toupper((int)(m->desc[0])); + + if (use_ext_addr) { + butterfly_set_extaddr(pgm, addr); + } else { + butterfly_set_addr(pgm, addr); + } + while (addr < max_addr) { + if ((max_addr - addr) < blocksize) { + blocksize = max_addr - addr; + }; + cmd[1] = (blocksize >> 8) & 0xff; + cmd[2] = blocksize & 0xff; + + butterfly_send(pgm, cmd, 4); + butterfly_recv(pgm, (char *)&m->buf[addr], blocksize); + + addr += blocksize; + + report_progress (addr, max_addr, NULL); + } /* while */ + } + + return addr * rd_size; +} + + +/* Signature byte reads are always 3 bytes. */ +static int butterfly_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) +{ + unsigned char tmp; + + if (m->size < 3) { + fprintf(stderr, "%s: memsize too small for sig byte read", progname); + return -1; + } + + butterfly_send(pgm, "s", 1); + butterfly_recv(pgm, (char *)m->buf, 3); + /* Returned signature has wrong order. */ + tmp = m->buf[2]; + m->buf[2] = m->buf[0]; + m->buf[0] = tmp; + + return 3; +} + + +void butterfly_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "butterfly"); + + /* + * mandatory functions + */ + pgm->rdy_led = butterfly_rdy_led; + pgm->err_led = butterfly_err_led; + pgm->pgm_led = butterfly_pgm_led; + pgm->vfy_led = butterfly_vfy_led; + pgm->initialize = butterfly_initialize; + pgm->display = butterfly_display; + pgm->enable = butterfly_enable; + pgm->disable = butterfly_disable; + pgm->powerup = butterfly_powerup; + pgm->powerdown = butterfly_powerdown; + pgm->program_enable = butterfly_program_enable; + pgm->chip_erase = butterfly_chip_erase; + pgm->open = butterfly_open; + pgm->close = butterfly_close; + pgm->read_byte = butterfly_read_byte; + pgm->write_byte = butterfly_write_byte; + + /* + * optional functions + */ + + pgm->paged_write = butterfly_paged_write; + pgm->paged_load = butterfly_paged_load; + + pgm->read_sig_bytes = butterfly_read_sig_bytes; + + pgm->setup = butterfly_setup; + pgm->teardown = butterfly_teardown; + pgm->flag = 0; +} + +void butterfly_mk_initpgm(PROGRAMMER * pgm) +{ + butterfly_initpgm(pgm); + strcpy(pgm->type, "butterfly_mk"); + pgm->flag = IS_BUTTERFLY_MK; +} diff --git a/avrdude/butterfly.h b/avrdude/butterfly.h new file mode 100644 index 00000000..aa4c58c7 --- /dev/null +++ b/avrdude/butterfly.h @@ -0,0 +1,36 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef butterfly_h +#define butterfly_h + +#ifdef __cplusplus +extern "C" { +#endif + +void butterfly_initpgm (PROGRAMMER * pgm); +void butterfly_mk_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif /* butterfly_h */ diff --git a/avrdude/config.c b/avrdude/config.c new file mode 100644 index 00000000..6f0b571d --- /dev/null +++ b/avrdude/config.c @@ -0,0 +1,307 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "config.h" +#include "config_gram.h" + +char default_programmer[MAX_STR_CONST]; +char default_parallel[PATH_MAX]; +char default_serial[PATH_MAX]; +double default_bitclock; + +char string_buf[MAX_STR_CONST]; +char *string_buf_ptr; + +LISTID string_list; +LISTID number_list; +PROGRAMMER * current_prog; +AVRPART * current_part; +AVRMEM * current_mem; +LISTID part_list; +LISTID programmers; + +int lineno; +const char * infile; + +extern char * yytext; + +#define DEBUG 0 + + +int init_config(void) +{ + string_list = lcreat(NULL, 0); + number_list = lcreat(NULL, 0); + current_prog = NULL; + current_part = NULL; + current_mem = 0; + part_list = lcreat(NULL, 0); + programmers = lcreat(NULL, 0); + + lineno = 1; + infile = NULL; + + return 0; +} + + + +int yywrap() +{ + return 1; +} + + +int yyerror(char * errmsg) +{ + fprintf(stderr, "%s at %s:%d\n", errmsg, infile, lineno); + exit(1); +} + + +TOKEN * new_token(int primary) +{ + TOKEN * tkn; + + tkn = (TOKEN *)malloc(sizeof(TOKEN)); + if (tkn == NULL) { + fprintf(stderr, "new_token(): out of memory\n"); + exit(1); + } + + memset(tkn, 0, sizeof(TOKEN)); + + tkn->primary = primary; + + return tkn; +} + + +void free_token(TOKEN * tkn) +{ + if (tkn) { + switch (tkn->primary) { + case TKN_STRING: + case TKN_ID: + if (tkn->value.string) + free(tkn->value.string); + tkn->value.string = NULL; + break; + } + + free(tkn); + } +} + + +void free_tokens(int n, ...) +{ + TOKEN * t; + va_list ap; + + va_start(ap, n); + while (n--) { + t = va_arg(ap, TOKEN *); + free_token(t); + } + va_end(ap); +} + + + +TOKEN * number(char * text) +{ + struct token_t * tkn; + + tkn = new_token(TKN_NUMBER); + tkn->value.type = V_NUM; + tkn->value.number = atof(text); + +#if DEBUG + fprintf(stderr, "NUMBER(%g)\n", tkn->value.number); +#endif + + return tkn; +} + + +TOKEN * hexnumber(char * text) +{ + struct token_t * tkn; + char * e; + + tkn = new_token(TKN_NUMBER); + tkn->value.type = V_NUM; + tkn->value.number = strtoul(text, &e, 16); + if ((e == text) || (*e != 0)) { + fprintf(stderr, "error at %s:%d: can't scan hex number \"%s\"\n", + infile, lineno, text); + exit(1); + } + +#if DEBUG + fprintf(stderr, "HEXNUMBER(%g)\n", tkn->value.number); +#endif + + return tkn; +} + + +TOKEN * string(char * text) +{ + struct token_t * tkn; + int len; + + tkn = new_token(TKN_STRING); + + len = strlen(text); + + tkn->value.type = V_STR; + tkn->value.string = (char *) malloc(len+1); + if (tkn->value.string == NULL) { + fprintf(stderr, "id(): out of memory\n"); + exit(1); + } + strcpy(tkn->value.string, text); + +#if DEBUG + fprintf(stderr, "STRING(%s)\n", tkn->value.string); +#endif + + return tkn; +} + + +TOKEN * id(char * text) +{ + struct token_t * tkn; + int len; + + tkn = new_token(TKN_ID); + + len = strlen(text); + + tkn->value.type = V_STR; + tkn->value.string = (char *) malloc(len+1); + if (tkn->value.string == NULL) { + fprintf(stderr, "id(): out of memory\n"); + exit(1); + } + strcpy(tkn->value.string, text); + +#if DEBUG + fprintf(stderr, "ID(%s)\n", tkn->value.string); +#endif + + return tkn; +} + + +TOKEN * keyword(int primary) +{ + struct token_t * tkn; + + tkn = new_token(primary); + + return tkn; +} + + +void print_token(TOKEN * tkn) +{ + if (!tkn) + return; + + fprintf(stderr, "token = %d = ", tkn->primary); + switch (tkn->primary) { + case TKN_NUMBER: + fprintf(stderr, "NUMBER, value=%g", tkn->value.number); + break; + + case TKN_STRING: + fprintf(stderr, "STRING, value=%s", tkn->value.string); + break; + + case TKN_ID: + fprintf(stderr, "ID, value=%s", tkn->value.string); + break; + + default: + fprintf(stderr, ""); + break; + } + + fprintf(stderr, "\n"); +} + + +void pyytext(void) +{ +#if DEBUG + fprintf(stderr, "TOKEN: \"%s\"\n", yytext); +#endif +} + + +char * dup_string(const char * str) +{ + char * s; + + s = strdup(str); + if (s == NULL) { + fprintf(stderr, "dup_string(): out of memory\n"); + exit(1); + } + + return s; +} + +int read_config(const char * file) +{ + FILE * f; + + f = fopen(file, "r"); + if (f == NULL) { + fprintf(stderr, "%s: can't open config file \"%s\": %s\n", + progname, file, strerror(errno)); + return -1; + } + + lineno = 1; + infile = file; + yyin = f; + + yyparse(); + + fclose(f); + + return 0; +} diff --git a/avrdude/config.h b/avrdude/config.h new file mode 100644 index 00000000..02355795 --- /dev/null +++ b/avrdude/config.h @@ -0,0 +1,109 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef config_h +#define config_h + +#include "lists.h" +#include "pindefs.h" +#include "avr.h" + + +#define MAX_STR_CONST 1024 + +enum { V_NONE, V_NUM, V_STR }; +typedef struct value_t { + int type; + double number; + char * string; +} VALUE; + + +typedef struct token_t { + int primary; + VALUE value; +} TOKEN; +typedef struct token_t *token_p; + + +extern FILE * yyin; +extern PROGRAMMER * current_prog; +extern AVRPART * current_part; +extern AVRMEM * current_mem; +extern int lineno; +extern const char * infile; +extern LISTID string_list; +extern LISTID number_list; +extern LISTID part_list; +extern LISTID programmers; +extern char default_programmer[]; +extern char default_parallel[]; +extern char default_serial[]; +extern double default_bitclock; + + + +#if !defined(HAS_YYSTYPE) +#define YYSTYPE token_p +#endif +extern YYSTYPE yylval; + +extern char string_buf[MAX_STR_CONST]; +extern char *string_buf_ptr; + +#ifdef __cplusplus +extern "C" { +#endif + +int yyparse(void); + + +int init_config(void); + +TOKEN * new_token(int primary); + +void free_token(TOKEN * tkn); + +void free_tokens(int n, ...); + +TOKEN * number(char * text); + +TOKEN * hexnumber(char * text); + +TOKEN * string(char * text); + +TOKEN * id(char * text); + +TOKEN * keyword(int primary); + +void print_token(TOKEN * tkn); + +void pyytext(void); + +char * dup_string(const char * str); + +int read_config(const char * file); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/config_gram.y b/avrdude/config_gram.y new file mode 100644 index 00000000..3e10cd46 --- /dev/null +++ b/avrdude/config_gram.y @@ -0,0 +1,1600 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ +%{ + +#include "ac_cfg.h" + +#include +#include +#include + +#include "avrdude.h" + +#include "config.h" +#include "lists.h" +#include "par.h" +#include "serbb.h" +#include "pindefs.h" +#include "ppi.h" +#include "pgm.h" +#include "stk500.h" +#include "arduino.h" +#include "buspirate.h" +#include "stk500v2.h" +#include "wiring.h" +#include "stk500generic.h" +#include "avr910.h" +#include "butterfly.h" +#include "usbasp.h" +#include "usbtiny.h" +#include "avr.h" +#include "jtagmkI.h" +#include "jtagmkII.h" +#include "avrftdi.h" + +#if defined(WIN32NATIVE) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif + +int yylex(void); +int yyerror(char * errmsg); + +static int assign_pin(int pinno, TOKEN * v, int invert); +static int which_opcode(TOKEN * opcode); +static int parse_cmdbits(OPCODE * op); + +%} + +%token K_READ +%token K_WRITE +%token K_READ_LO +%token K_READ_HI +%token K_WRITE_LO +%token K_WRITE_HI +%token K_LOADPAGE_LO +%token K_LOADPAGE_HI +%token K_LOAD_EXT_ADDR +%token K_WRITEPAGE +%token K_CHIP_ERASE +%token K_PGM_ENABLE + +%token K_MEMORY + +%token K_PAGE_SIZE +%token K_PAGED + +%token K_ARDUINO +%token K_AVRFTDI +%token K_BAUDRATE +%token K_BS2 +%token K_BUFF +%token K_BUSPIRATE +%token K_CHIP_ERASE_DELAY +%token K_DEDICATED +%token K_DEFAULT_PARALLEL +%token K_DEFAULT_PROGRAMMER +%token K_DEFAULT_SERIAL +%token K_DEFAULT_BITCLOCK +%token K_DESC +%token K_DEVICECODE +%token K_DRAGON_DW +%token K_DRAGON_HVSP +%token K_DRAGON_ISP +%token K_DRAGON_JTAG +%token K_DRAGON_PDI +%token K_DRAGON_PP +%token K_STK500_DEVCODE +%token K_AVR910_DEVCODE +%token K_EEPROM +%token K_ERRLED +%token K_FLASH +%token K_ID +%token K_IO +%token K_JTAG_MKI +%token K_JTAG_MKII +%token K_JTAG_MKII_AVR32 +%token K_JTAG_MKII_DW +%token K_JTAG_MKII_ISP +%token K_JTAG_MKII_PDI +%token K_LOADPAGE +%token K_MAX_WRITE_DELAY +%token K_MIN_WRITE_DELAY +%token K_MISO +%token K_MOSI +%token K_NUM_PAGES +%token K_NVM_BASE +%token K_OFFSET +%token K_PAGEL +%token K_PAR +%token K_PARALLEL +%token K_PART +%token K_PGMLED +%token K_PROGRAMMER +%token K_PSEUDO +%token K_PWROFF_AFTER_WRITE +%token K_RDYLED +%token K_READBACK_P1 +%token K_READBACK_P2 +%token K_READMEM +%token K_RESET +%token K_RETRY_PULSE +%token K_SERBB +%token K_SERIAL +%token K_SCK +%token K_SIGNATURE +%token K_SIZE +%token K_STK500 +%token K_STK500HVSP +%token K_STK500PP +%token K_STK500V2 +%token K_STK500GENERIC +%token K_STK600 +%token K_STK600HVSP +%token K_STK600PP +%token K_AVR910 +%token K_USBASP +%token K_USBDEV +%token K_USBSN +%token K_USBTINY +%token K_USBPID +%token K_USBPRODUCT +%token K_USBVENDOR +%token K_USBVID +%token K_BUTTERFLY +%token K_BUTTERFLY_MK +%token K_TYPE +%token K_VCC +%token K_VFYLED +%token K_WIRING + +%token K_NO +%token K_YES + +/* stk500 v2 xml file parameters */ +/* ISP */ +%token K_TIMEOUT +%token K_STABDELAY +%token K_CMDEXEDELAY +%token K_HVSPCMDEXEDELAY +%token K_SYNCHLOOPS +%token K_BYTEDELAY +%token K_POLLVALUE +%token K_POLLINDEX +%token K_PREDELAY +%token K_POSTDELAY +%token K_POLLMETHOD +%token K_MODE +%token K_DELAY +%token K_BLOCKSIZE +%token K_READSIZE +/* HV mode */ +%token K_HVENTERSTABDELAY +%token K_PROGMODEDELAY +%token K_LATCHCYCLES +%token K_TOGGLEVTG +%token K_POWEROFFDELAY +%token K_RESETDELAYMS +%token K_RESETDELAYUS +%token K_HVLEAVESTABDELAY +%token K_RESETDELAY +%token K_SYNCHCYCLES +%token K_HVCMDEXEDELAY + +%token K_CHIPERASEPULSEWIDTH +%token K_CHIPERASEPOLLTIMEOUT +%token K_CHIPERASETIME +%token K_PROGRAMFUSEPULSEWIDTH +%token K_PROGRAMFUSEPOLLTIMEOUT +%token K_PROGRAMLOCKPULSEWIDTH +%token K_PROGRAMLOCKPOLLTIMEOUT + +%token K_PP_CONTROLSTACK +%token K_HVSP_CONTROLSTACK + +/* JTAG ICE mkII specific parameters */ +%token K_ALLOWFULLPAGEBITSTREAM /* + * Internal parameter for the JTAG + * ICE; describes the internal JTAG + * streaming behaviour inside the MCU. + * 1 for all older chips, 0 for newer + * MCUs. + */ +%token K_ENABLEPAGEPROGRAMMING /* ? yes for mega256*, mega406 */ +%token K_HAS_JTAG /* MCU has JTAG i/f. */ +%token K_HAS_DW /* MCU has debugWire i/f. */ +%token K_HAS_PDI /* MCU has PDI i/f rather than ISP (ATxmega). */ +%token K_HAS_TPI /* MCU has TPI i/f rather than ISP (ATtiny4/5/9/10). */ +%token K_IDR /* address of OCD register in IO space */ +%token K_IS_AVR32 /* chip is in the avr32 family */ +%token K_RAMPZ /* address of RAMPZ reg. in IO space */ +%token K_SPMCR /* address of SPMC[S]R in memory space */ +%token K_EECR /* address of EECR in memory space */ +%token K_FLASH_INSTR /* flash instructions */ +%token K_EEPROM_INSTR /* EEPROM instructions */ + +%token TKN_COMMA +%token TKN_EQUAL +%token TKN_SEMI +%token TKN_TILDE +%token TKN_NUMBER +%token TKN_STRING +%token TKN_ID + +%start configuration + +%% + +configuration : + /* empty */ | config +; + +config : + def | + config def +; + + +def : + prog_def TKN_SEMI | + + part_def TKN_SEMI | + + K_DEFAULT_PROGRAMMER TKN_EQUAL TKN_STRING TKN_SEMI { + strncpy(default_programmer, $3->value.string, MAX_STR_CONST); + default_programmer[MAX_STR_CONST-1] = 0; + free_token($3); + } | + + K_DEFAULT_PARALLEL TKN_EQUAL TKN_STRING TKN_SEMI { + strncpy(default_parallel, $3->value.string, PATH_MAX); + default_parallel[PATH_MAX-1] = 0; + free_token($3); + } | + + K_DEFAULT_SERIAL TKN_EQUAL TKN_STRING TKN_SEMI { + strncpy(default_serial, $3->value.string, PATH_MAX); + default_serial[PATH_MAX-1] = 0; + free_token($3); + } | + + K_DEFAULT_BITCLOCK TKN_EQUAL TKN_NUMBER TKN_SEMI { + default_bitclock = $3->value.number; + free_token($3); + } +; + + +prog_def : + K_PROGRAMMER + { current_prog = pgm_new(); + strcpy(current_prog->config_file, infile); + current_prog->lineno = lineno; + } + prog_parms + { + if (lsize(current_prog->id) == 0) { + fprintf(stderr, + "%s: error at %s:%d: required parameter id not specified\n", + progname, infile, lineno); + exit(1); + } + if (current_prog->type[0] == 0) { + fprintf(stderr, "%s: error at %s:%d: programmer type not specified\n", + progname, infile, lineno); + exit(1); + } + PUSH(programmers, current_prog); + current_prog = NULL; + } +; + + +part_def : + K_PART + { + current_part = avr_new_part(); + strcpy(current_part->config_file, infile); + current_part->lineno = lineno; + } + part_parms + { + LNODEID ln; + AVRMEM * m; + + if (current_part->id[0] == 0) { + fprintf(stderr, + "%s: error at %s:%d: required parameter id not specified\n", + progname, infile, lineno); + exit(1); + } + + /* + * perform some sanity checking, and compute the number of bits + * to shift a page for constructing the page address for + * page-addressed memories. + */ + for (ln=lfirst(current_part->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + if (m->paged) { + if (m->page_size == 0) { + fprintf(stderr, + "%s: error at %s:%d: must specify page_size for paged " + "memory\n", + progname, infile, lineno); + exit(1); + } + if (m->num_pages == 0) { + fprintf(stderr, + "%s: error at %s:%d: must specify num_pages for paged " + "memory\n", + progname, infile, lineno); + exit(1); + } + if (m->size != m->page_size * m->num_pages) { + fprintf(stderr, + "%s: error at %s:%d: page size (%u) * num_pages (%u) = " + "%u does not match memory size (%u)\n", + progname, infile, lineno, + m->page_size, + m->num_pages, + m->page_size * m->num_pages, + m->size); + exit(1); + } + + } + } + + PUSH(part_list, current_part); + current_part = NULL; + } +; + + +string_list : + TKN_STRING { ladd(string_list, $1); } | + string_list TKN_COMMA TKN_STRING { ladd(string_list, $3); } +; + + +num_list : + TKN_NUMBER { ladd(number_list, $1); } | + num_list TKN_COMMA TKN_NUMBER { ladd(number_list, $3); } +; + + +prog_parms : + prog_parm TKN_SEMI | + prog_parms prog_parm TKN_SEMI +; + + +prog_parm : + K_ID TKN_EQUAL string_list { + { + TOKEN * t; + while (lsize(string_list)) { + t = lrmv_n(string_list, 1); + ladd(current_prog->id, dup_string(t->value.string)); + free_token(t); + } + } + } | + + K_TYPE TKN_EQUAL K_PAR { + { + par_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_SERBB { + { + serbb_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK500 { + { + stk500_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK500V2 { + { + stk500v2_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_WIRING { + { + wiring_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK500HVSP { + { + stk500hvsp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK500PP { + { + stk500pp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK500GENERIC { + { + stk500generic_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_ARDUINO { + { + arduino_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_AVRFTDI { + { + avrftdi_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_BUSPIRATE { + { + buspirate_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK600 { + { + stk600_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK600HVSP { + { + stk600hvsp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK600PP { + { + stk600pp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_AVR910 { + { + avr910_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_USBASP { + { + usbasp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_USBTINY { + { + usbtiny_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_BUTTERFLY { + { + butterfly_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_BUTTERFLY_MK { + { + butterfly_mk_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_JTAG_MKI { + { + jtagmkI_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_JTAG_MKII { + { + jtagmkII_initpgm(current_prog); + } + } | + K_TYPE TKN_EQUAL K_JTAG_MKII_AVR32 { + { + jtagmkII_avr32_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_JTAG_MKII_DW { + { + jtagmkII_dw_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_JTAG_MKII_ISP { + { + stk500v2_jtagmkII_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_JTAG_MKII_PDI { + { + jtagmkII_pdi_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_DRAGON_DW { + { + jtagmkII_dragon_dw_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_DRAGON_HVSP { + { + stk500v2_dragon_hvsp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_DRAGON_ISP { + { + stk500v2_dragon_isp_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_DRAGON_JTAG { + { + jtagmkII_dragon_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_DRAGON_PDI { + { + jtagmkII_dragon_pdi_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_DRAGON_PP { + { + stk500v2_dragon_pp_initpgm(current_prog); + } + } | + + K_DESC TKN_EQUAL TKN_STRING { + strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN); + current_prog->desc[PGM_DESCLEN-1] = 0; + free_token($3); + } | + + K_VCC TKN_EQUAL num_list { + { + TOKEN * t; + int pin; + + current_prog->pinno[PPI_AVR_VCC] = 0; + + while (lsize(number_list)) { + t = lrmv_n(number_list, 1); + pin = t->value.number; + current_prog->pinno[PPI_AVR_VCC] |= (1 << pin); + + free_token(t); + } + } + } | + + K_BUFF TKN_EQUAL num_list { + { + TOKEN * t; + int pin; + + current_prog->pinno[PPI_AVR_BUFF] = 0; + + while (lsize(number_list)) { + t = lrmv_n(number_list, 1); + pin = t->value.number; + current_prog->pinno[PPI_AVR_BUFF] |= (1 << pin); + + free_token(t); + } + } + } | + K_USBDEV TKN_EQUAL TKN_STRING { + { + strncpy(current_prog->usbdev, $3->value.string, PGM_USBSTRINGLEN); + current_prog->usbdev[PGM_USBSTRINGLEN-1] = 0; + free_token($3); + } + } | + K_USBVID TKN_EQUAL TKN_NUMBER { + { + current_prog->usbvid = $3->value.number; + } + } | + + K_USBPID TKN_EQUAL TKN_NUMBER { + { + current_prog->usbpid = $3->value.number; + } + } | + + K_USBSN TKN_EQUAL TKN_STRING { + { + strncpy(current_prog->usbsn, $3->value.string, PGM_USBSTRINGLEN); + current_prog->usbsn[PGM_USBSTRINGLEN-1] = 0; + free_token($3); + } + } | + + K_USBVENDOR TKN_EQUAL TKN_STRING { + { + strncpy(current_prog->usbvendor, $3->value.string, PGM_USBSTRINGLEN); + current_prog->usbvendor[PGM_USBSTRINGLEN-1] = 0; + free_token($3); + } + } | + + K_USBPRODUCT TKN_EQUAL TKN_STRING { + { + strncpy(current_prog->usbproduct, $3->value.string, PGM_USBSTRINGLEN); + current_prog->usbproduct[PGM_USBSTRINGLEN-1] = 0; + free_token($3); + } + } | + + K_BAUDRATE TKN_EQUAL TKN_NUMBER { + { + current_prog->baudrate = $3->value.number; + } + } | + + K_RESET TKN_EQUAL TKN_NUMBER { free_token($1); + assign_pin(PIN_AVR_RESET, $3, 0); } | + K_SCK TKN_EQUAL TKN_NUMBER { free_token($1); + assign_pin(PIN_AVR_SCK, $3, 0); } | + K_MOSI TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $3, 0); } | + K_MISO TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MISO, $3, 0); } | + K_ERRLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_ERR, $3, 0); } | + K_RDYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_RDY, $3, 0); } | + K_PGMLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_PGM, $3, 0); } | + K_VFYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_VFY, $3, 0); } | + + K_RESET TKN_EQUAL TKN_TILDE TKN_NUMBER { free_token($1); + assign_pin(PIN_AVR_RESET, $4, 1); } | + K_SCK TKN_EQUAL TKN_TILDE TKN_NUMBER { free_token($1); + assign_pin(PIN_AVR_SCK, $4, 1); } | + K_MOSI TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $4, 1); } | + K_MISO TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_AVR_MISO, $4, 1); } | + K_ERRLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_ERR, $4, 1); } | + K_RDYLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_RDY, $4, 1); } | + K_PGMLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_PGM, $4, 1); } | + K_VFYLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_VFY, $4, 1); } +; + + +opcode : + K_READ | + K_WRITE | + K_READ_LO | + K_READ_HI | + K_WRITE_LO | + K_WRITE_HI | + K_LOADPAGE_LO | + K_LOADPAGE_HI | + K_LOAD_EXT_ADDR | + K_WRITEPAGE | + K_CHIP_ERASE | + K_PGM_ENABLE +; + + +part_parms : + part_parm TKN_SEMI | + part_parms part_parm TKN_SEMI +; + + +reset_disposition : + K_DEDICATED | K_IO +; + +parallel_modes : + yesno | K_PSEUDO +; + +retry_lines : + K_RESET | K_SCK +; + +part_parm : + K_ID TKN_EQUAL TKN_STRING + { + strncpy(current_part->id, $3->value.string, AVR_IDLEN); + current_part->id[AVR_IDLEN-1] = 0; + free_token($3); + } | + + K_DESC TKN_EQUAL TKN_STRING + { + strncpy(current_part->desc, $3->value.string, AVR_DESCLEN); + current_part->desc[AVR_DESCLEN-1] = 0; + free_token($3); + } | + + K_DEVICECODE TKN_EQUAL TKN_NUMBER { + { + fprintf(stderr, + "%s: error at %s:%d: devicecode is deprecated, use " + "stk500_devcode instead\n", + progname, infile, lineno); + exit(1); + } + } | + + K_STK500_DEVCODE TKN_EQUAL TKN_NUMBER { + { + current_part->stk500_devcode = $3->value.number; + free_token($3); + } + } | + + K_AVR910_DEVCODE TKN_EQUAL TKN_NUMBER { + { + current_part->avr910_devcode = $3->value.number; + free_token($3); + } + } | + + K_SIGNATURE TKN_EQUAL TKN_NUMBER TKN_NUMBER TKN_NUMBER { + { + current_part->signature[0] = $3->value.number; + current_part->signature[1] = $4->value.number; + current_part->signature[2] = $5->value.number; + free_token($3); + free_token($4); + free_token($5); + } + } | + + K_PP_CONTROLSTACK TKN_EQUAL num_list { + { + TOKEN * t; + unsigned nbytes; + int ok; + + if (current_part->ctl_stack_type != CTL_STACK_NONE) + { + fprintf(stderr, + "%s: error at line %d of %s: " + "control stack already defined\n", + progname, lineno, infile); + exit(1); + } + + current_part->ctl_stack_type = CTL_STACK_PP; + nbytes = 0; + ok = 1; + + while (lsize(number_list)) { + t = lrmv_n(number_list, 1); + if (nbytes < CTL_STACK_SIZE) + { + current_part->controlstack[nbytes] = t->value.number; + nbytes++; + } + else + { + ok = 0; + } + free_token(t); + } + if (!ok) + { + fprintf(stderr, + "%s: Warning: line %d of %s: " + "too many bytes in control stack\n", + progname, lineno, infile); + } + } + } | + + K_HVSP_CONTROLSTACK TKN_EQUAL num_list { + { + TOKEN * t; + unsigned nbytes; + int ok; + + if (current_part->ctl_stack_type != CTL_STACK_NONE) + { + fprintf(stderr, + "%s: error at line %d of %s: " + "control stack already defined\n", + progname, lineno, infile); + exit(1); + } + + current_part->ctl_stack_type = CTL_STACK_HVSP; + nbytes = 0; + ok = 1; + + while (lsize(number_list)) { + t = lrmv_n(number_list, 1); + if (nbytes < CTL_STACK_SIZE) + { + current_part->controlstack[nbytes] = t->value.number; + nbytes++; + } + else + { + ok = 0; + } + free_token(t); + } + if (!ok) + { + fprintf(stderr, + "%s: Warning: line %d of %s: " + "too many bytes in control stack\n", + progname, lineno, infile); + } + } + } | + + K_FLASH_INSTR TKN_EQUAL num_list { + { + TOKEN * t; + unsigned nbytes; + int ok; + + nbytes = 0; + ok = 1; + + while (lsize(number_list)) { + t = lrmv_n(number_list, 1); + if (nbytes < FLASH_INSTR_SIZE) + { + current_part->flash_instr[nbytes] = t->value.number; + nbytes++; + } + else + { + ok = 0; + } + free_token(t); + } + if (!ok) + { + fprintf(stderr, + "%s: Warning: line %d of %s: " + "too many bytes in flash instructions\n", + progname, lineno, infile); + } + } + } | + + K_EEPROM_INSTR TKN_EQUAL num_list { + { + TOKEN * t; + unsigned nbytes; + int ok; + + nbytes = 0; + ok = 1; + + while (lsize(number_list)) { + t = lrmv_n(number_list, 1); + if (nbytes < EEPROM_INSTR_SIZE) + { + current_part->eeprom_instr[nbytes] = t->value.number; + nbytes++; + } + else + { + ok = 0; + } + free_token(t); + } + if (!ok) + { + fprintf(stderr, + "%s: Warning: line %d of %s: " + "too many bytes in EEPROM instructions\n", + progname, lineno, infile); + } + } + } | + + K_CHIP_ERASE_DELAY TKN_EQUAL TKN_NUMBER + { + current_part->chip_erase_delay = $3->value.number; + free_token($3); + } | + + K_PAGEL TKN_EQUAL TKN_NUMBER + { + current_part->pagel = $3->value.number; + free_token($3); + } | + + K_BS2 TKN_EQUAL TKN_NUMBER + { + current_part->bs2 = $3->value.number; + free_token($3); + } | + + K_RESET TKN_EQUAL reset_disposition + { + if ($3->primary == K_DEDICATED) + current_part->reset_disposition = RESET_DEDICATED; + else if ($3->primary == K_IO) + current_part->reset_disposition = RESET_IO; + + free_tokens(2, $1, $3); + } | + + K_TIMEOUT TKN_EQUAL TKN_NUMBER + { + current_part->timeout = $3->value.number; + free_token($3); + } | + + K_STABDELAY TKN_EQUAL TKN_NUMBER + { + current_part->stabdelay = $3->value.number; + free_token($3); + } | + + K_CMDEXEDELAY TKN_EQUAL TKN_NUMBER + { + current_part->cmdexedelay = $3->value.number; + free_token($3); + } | + + K_HVSPCMDEXEDELAY TKN_EQUAL TKN_NUMBER + { + current_part->hvspcmdexedelay = $3->value.number; + free_token($3); + } | + + K_SYNCHLOOPS TKN_EQUAL TKN_NUMBER + { + current_part->synchloops = $3->value.number; + free_token($3); + } | + + K_BYTEDELAY TKN_EQUAL TKN_NUMBER + { + current_part->bytedelay = $3->value.number; + free_token($3); + } | + + K_POLLVALUE TKN_EQUAL TKN_NUMBER + { + current_part->pollvalue = $3->value.number; + free_token($3); + } | + + K_POLLINDEX TKN_EQUAL TKN_NUMBER + { + current_part->pollindex = $3->value.number; + free_token($3); + } | + + K_PREDELAY TKN_EQUAL TKN_NUMBER + { + current_part->predelay = $3->value.number; + free_token($3); + } | + + K_POSTDELAY TKN_EQUAL TKN_NUMBER + { + current_part->postdelay = $3->value.number; + free_token($3); + } | + + K_POLLMETHOD TKN_EQUAL TKN_NUMBER + { + current_part->pollmethod = $3->value.number; + free_token($3); + } | + + K_HVENTERSTABDELAY TKN_EQUAL TKN_NUMBER + { + current_part->hventerstabdelay = $3->value.number; + free_token($3); + } | + + K_PROGMODEDELAY TKN_EQUAL TKN_NUMBER + { + current_part->progmodedelay = $3->value.number; + free_token($3); + } | + + K_LATCHCYCLES TKN_EQUAL TKN_NUMBER + { + current_part->latchcycles = $3->value.number; + free_token($3); + } | + + K_TOGGLEVTG TKN_EQUAL TKN_NUMBER + { + current_part->togglevtg = $3->value.number; + free_token($3); + } | + + K_POWEROFFDELAY TKN_EQUAL TKN_NUMBER + { + current_part->poweroffdelay = $3->value.number; + free_token($3); + } | + + K_RESETDELAYMS TKN_EQUAL TKN_NUMBER + { + current_part->resetdelayms = $3->value.number; + free_token($3); + } | + + K_RESETDELAYUS TKN_EQUAL TKN_NUMBER + { + current_part->resetdelayus = $3->value.number; + free_token($3); + } | + + K_HVLEAVESTABDELAY TKN_EQUAL TKN_NUMBER + { + current_part->hvleavestabdelay = $3->value.number; + free_token($3); + } | + + K_RESETDELAY TKN_EQUAL TKN_NUMBER + { + current_part->resetdelay = $3->value.number; + free_token($3); + } | + + K_CHIPERASEPULSEWIDTH TKN_EQUAL TKN_NUMBER + { + current_part->chiperasepulsewidth = $3->value.number; + free_token($3); + } | + + K_CHIPERASEPOLLTIMEOUT TKN_EQUAL TKN_NUMBER + { + current_part->chiperasepolltimeout = $3->value.number; + free_token($3); + } | + + K_CHIPERASETIME TKN_EQUAL TKN_NUMBER + { + current_part->chiperasetime = $3->value.number; + free_token($3); + } | + + K_PROGRAMFUSEPULSEWIDTH TKN_EQUAL TKN_NUMBER + { + current_part->programfusepulsewidth = $3->value.number; + free_token($3); + } | + + K_PROGRAMFUSEPOLLTIMEOUT TKN_EQUAL TKN_NUMBER + { + current_part->programfusepolltimeout = $3->value.number; + free_token($3); + } | + + K_PROGRAMLOCKPULSEWIDTH TKN_EQUAL TKN_NUMBER + { + current_part->programlockpulsewidth = $3->value.number; + free_token($3); + } | + + K_PROGRAMLOCKPOLLTIMEOUT TKN_EQUAL TKN_NUMBER + { + current_part->programlockpolltimeout = $3->value.number; + free_token($3); + } | + + K_SYNCHCYCLES TKN_EQUAL TKN_NUMBER + { + current_part->synchcycles = $3->value.number; + free_token($3); + } | + + K_HAS_JTAG TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_HAS_JTAG; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_HAS_JTAG; + + free_token($3); + } | + + K_HAS_DW TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_HAS_DW; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_HAS_DW; + + free_token($3); + } | + + K_HAS_PDI TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_HAS_PDI; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_HAS_PDI; + + free_token($3); + } | + + K_HAS_TPI TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_HAS_TPI; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_HAS_TPI; + + free_token($3); + } | + + K_IS_AVR32 TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_AVR32; + else if ($3->primary == K_NO) + current_part->flags &= AVRPART_AVR32; + + free_token($3); + } | + + K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_ALLOWFULLPAGEBITSTREAM; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_ALLOWFULLPAGEBITSTREAM; + + free_token($3); + } | + + K_ENABLEPAGEPROGRAMMING TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_ENABLEPAGEPROGRAMMING; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_ENABLEPAGEPROGRAMMING; + + free_token($3); + } | + + K_IDR TKN_EQUAL TKN_NUMBER + { + current_part->idr = $3->value.number; + free_token($3); + } | + + K_RAMPZ TKN_EQUAL TKN_NUMBER + { + current_part->rampz = $3->value.number; + free_token($3); + } | + + K_SPMCR TKN_EQUAL TKN_NUMBER + { + current_part->spmcr = $3->value.number; + free_token($3); + } | + + K_EECR TKN_EQUAL TKN_NUMBER + { + current_part->eecr = $3->value.number; + free_token($3); + } | + + K_NVM_BASE TKN_EQUAL TKN_NUMBER + { + current_part->nvm_base = $3->value.number; + free_token($3); + } | + + K_SERIAL TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_SERIALOK; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_SERIALOK; + + free_token($3); + } | + + K_PARALLEL TKN_EQUAL parallel_modes + { + if ($3->primary == K_YES) { + current_part->flags |= AVRPART_PARALLELOK; + current_part->flags &= ~AVRPART_PSEUDOPARALLEL; + } + else if ($3->primary == K_NO) { + current_part->flags &= ~AVRPART_PARALLELOK; + current_part->flags &= ~AVRPART_PSEUDOPARALLEL; + } + else if ($3->primary == K_PSEUDO) { + current_part->flags |= AVRPART_PARALLELOK; + current_part->flags |= AVRPART_PSEUDOPARALLEL; + } + + + free_token($3); + } | + + K_RETRY_PULSE TKN_EQUAL retry_lines + { + switch ($3->primary) { + case K_RESET : + current_part->retry_pulse = PIN_AVR_RESET; + break; + case K_SCK : + current_part->retry_pulse = PIN_AVR_SCK; + break; + } + + free_token($1); + } | + + +/* + K_EEPROM { current_mem = AVR_M_EEPROM; } + mem_specs | + + K_FLASH { current_mem = AVR_M_FLASH; } + mem_specs | +*/ + + K_MEMORY TKN_STRING + { + current_mem = avr_new_memtype(); + strcpy(current_mem->desc, strdup($2->value.string)); + free_token($2); + } + mem_specs + { + ladd(current_part->mem, current_mem); + current_mem = NULL; + } | + + opcode TKN_EQUAL string_list { + { + int opnum; + OPCODE * op; + + opnum = which_opcode($1); + op = avr_new_opcode(); + parse_cmdbits(op); + current_part->op[opnum] = op; + + free_token($1); + } + } +; + + +yesno : + K_YES | K_NO +; + + +mem_specs : + mem_spec TKN_SEMI | + mem_specs mem_spec TKN_SEMI +; + + +mem_spec : + K_PAGED TKN_EQUAL yesno + { + current_mem->paged = $3->primary == K_YES ? 1 : 0; + free_token($3); + } | + + K_SIZE TKN_EQUAL TKN_NUMBER + { + current_mem->size = $3->value.number; + free_token($3); + } | + + + K_PAGE_SIZE TKN_EQUAL TKN_NUMBER + { + current_mem->page_size = $3->value.number; + free_token($3); + } | + + K_NUM_PAGES TKN_EQUAL TKN_NUMBER + { + current_mem->num_pages = $3->value.number; + free_token($3); + } | + + K_OFFSET TKN_EQUAL TKN_NUMBER + { + current_mem->offset = $3->value.number; + free_token($3); + } | + + K_MIN_WRITE_DELAY TKN_EQUAL TKN_NUMBER + { + current_mem->min_write_delay = $3->value.number; + free_token($3); + } | + + K_MAX_WRITE_DELAY TKN_EQUAL TKN_NUMBER + { + current_mem->max_write_delay = $3->value.number; + free_token($3); + } | + + K_PWROFF_AFTER_WRITE TKN_EQUAL yesno + { + current_mem->pwroff_after_write = $3->primary == K_YES ? 1 : 0; + free_token($3); + } | + + K_READBACK_P1 TKN_EQUAL TKN_NUMBER + { + current_mem->readback[0] = $3->value.number; + free_token($3); + } | + + K_READBACK_P2 TKN_EQUAL TKN_NUMBER + { + current_mem->readback[1] = $3->value.number; + free_token($3); + } | + + + K_MODE TKN_EQUAL TKN_NUMBER + { + current_mem->mode = $3->value.number; + free_token($3); + } | + + K_DELAY TKN_EQUAL TKN_NUMBER + { + current_mem->delay = $3->value.number; + free_token($3); + } | + + K_BLOCKSIZE TKN_EQUAL TKN_NUMBER + { + current_mem->blocksize = $3->value.number; + free_token($3); + } | + + K_READSIZE TKN_EQUAL TKN_NUMBER + { + current_mem->readsize = $3->value.number; + free_token($3); + } | + + K_POLLINDEX TKN_EQUAL TKN_NUMBER + { + current_mem->pollindex = $3->value.number; + free_token($3); + } | + + + opcode TKN_EQUAL string_list { + { + int opnum; + OPCODE * op; + + opnum = which_opcode($1); + op = avr_new_opcode(); + parse_cmdbits(op); + current_mem->op[opnum] = op; + + free_token($1); + } + } +; + + +%% + +#if 0 +static char * vtypestr(int type) +{ + switch (type) { + case V_NUM : return "NUMERIC"; + case V_STR : return "STRING"; + default: + return ""; + } +} +#endif + + +static int assign_pin(int pinno, TOKEN * v, int invert) +{ + int value; + + value = v->value.number; + + if ((value <= 0) || (value >= 18)) { + fprintf(stderr, + "%s: error at line %d of %s: pin must be in the " + "range 1-17\n", + progname, lineno, infile); + exit(1); + } + if (invert) + value |= PIN_INVERSE; + + current_prog->pinno[pinno] = value; + + return 0; +} + + +static int which_opcode(TOKEN * opcode) +{ + switch (opcode->primary) { + case K_READ : return AVR_OP_READ; break; + case K_WRITE : return AVR_OP_WRITE; break; + case K_READ_LO : return AVR_OP_READ_LO; break; + case K_READ_HI : return AVR_OP_READ_HI; break; + case K_WRITE_LO : return AVR_OP_WRITE_LO; break; + case K_WRITE_HI : return AVR_OP_WRITE_HI; break; + case K_LOADPAGE_LO : return AVR_OP_LOADPAGE_LO; break; + case K_LOADPAGE_HI : return AVR_OP_LOADPAGE_HI; break; + case K_LOAD_EXT_ADDR : return AVR_OP_LOAD_EXT_ADDR; break; + case K_WRITEPAGE : return AVR_OP_WRITEPAGE; break; + case K_CHIP_ERASE : return AVR_OP_CHIP_ERASE; break; + case K_PGM_ENABLE : return AVR_OP_PGM_ENABLE; break; + default : + fprintf(stderr, + "%s: error at %s:%d: invalid opcode\n", + progname, infile, lineno); + exit(1); + break; + } +} + + +static int parse_cmdbits(OPCODE * op) +{ + TOKEN * t; + int bitno; + char ch; + char * e; + char * q; + int len; + char * s, *brkt = NULL; + + bitno = 32; + while (lsize(string_list)) { + + t = lrmv_n(string_list, 1); + + s = strtok_r(t->value.string, " ", &brkt); + while (s != NULL) { + + bitno--; + if (bitno < 0) { + fprintf(stderr, + "%s: error at %s:%d: too many opcode bits for instruction\n", + progname, infile, lineno); + exit(1); + } + + len = strlen(s); + + if (len == 0) { + fprintf(stderr, + "%s: error at %s:%d: invalid bit specifier \"\"\n", + progname, infile, lineno); + exit(1); + } + + ch = s[0]; + + if (len == 1) { + switch (ch) { + case '1': + op->bit[bitno].type = AVR_CMDBIT_VALUE; + op->bit[bitno].value = 1; + op->bit[bitno].bitno = bitno % 8; + break; + case '0': + op->bit[bitno].type = AVR_CMDBIT_VALUE; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + case 'x': + op->bit[bitno].type = AVR_CMDBIT_IGNORE; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + case 'a': + op->bit[bitno].type = AVR_CMDBIT_ADDRESS; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = 8*(bitno/8) + bitno % 8; + break; + case 'i': + op->bit[bitno].type = AVR_CMDBIT_INPUT; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + case 'o': + op->bit[bitno].type = AVR_CMDBIT_OUTPUT; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + default : + fprintf(stderr, + "%s: error at %s:%d: invalid bit specifier '%c'\n", + progname, infile, lineno, ch); + exit(1); + break; + } + } + else { + if (ch == 'a') { + q = &s[1]; + op->bit[bitno].bitno = strtol(q, &e, 0); + if ((e == q)||(*e != 0)) { + fprintf(stderr, + "%s: error at %s:%d: can't parse bit number from \"%s\"\n", + progname, infile, lineno, q); + exit(1); + } + op->bit[bitno].type = AVR_CMDBIT_ADDRESS; + op->bit[bitno].value = 0; + } + else { + fprintf(stderr, + "%s: error at %s:%d: invalid bit specifier \"%s\"\n", + progname, infile, lineno, s); + exit(1); + } + } + + s = strtok_r(NULL, " ", &brkt); + } + + free_token(t); + + } /* while */ + + return 0; +} + + diff --git a/avrdude/configure.ac b/avrdude/configure.ac new file mode 100644 index 00000000..b5ba7cf8 --- /dev/null +++ b/avrdude/configure.ac @@ -0,0 +1,385 @@ +# +# avrdude - A Downloader/Uploader for AVR device programmers +# Copyright (C) 2003, 2004 Theodore A. Roth +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# $Id$ +# + +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.57) +AC_INIT(avrdude, 5.11, avrdude-dev@nongnu.org) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AC_CONFIG_SRCDIR([main.c]) +AM_INIT_AUTOMAKE +AM_CONFIG_HEADER(ac_cfg.h) + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_YACC +AC_PROG_LEX +AC_PROG_RANLIB + +dnl Makefile.am:77: compiling `config_gram.c' with per-target flags requires `AM_PROG_CC_C_O' in `configure.ac' +AM_PROG_CC_C_O + +# Checks for libraries. +AC_CHECK_LIB([termcap], [tputs]) +AC_CHECK_LIB([ncurses], [tputs]) +AC_CHECK_LIB([readline], [readline]) +AC_SEARCH_LIBS([gethostent], [nsl]) +AC_SEARCH_LIBS([setsockopt], [socket]) +AH_TEMPLATE([HAVE_LIBUSB], + [Define if USB support is enabled via libusb]) +AC_CHECK_LIB([usb], [usb_get_string_simple], [have_libusb=yes]) +if test x$have_libusb = xyes; then + case $target in + *-*-darwin*) + LIBUSB="-lusb -framework CoreFoundation -framework IOKit" + ;; + *) + LIBUSB="-lusb" + ;; + esac + AC_DEFINE([HAVE_LIBUSB]) +fi +AC_SUBST(LIBUSB, $LIBUSB) + +AH_TEMPLATE([HAVE_LIBUSB_1_0], + [Define if USB support is enabled via libusb 1.0]) +AC_CHECK_LIB([usb-1.0], [libusb_init], [have_libusb_1_0=yes]) +if test x$have_libusb_1_0 = xyes; then + case $target in + *-*-darwin*) + LIBUSB_1_0="-lusb-1.0 -framework CoreFoundation -framework IOKit" + ;; + *) + LIBUSB_1_0="-lusb-1.0" + ;; + esac + AC_DEFINE([HAVE_LIBUSB_1_0]) + AC_CHECK_HEADERS([libusb-1.0/libusb.h]) + AC_CHECK_HEADERS([libusb.h]) +fi +AH_TEMPLATE([HAVE_LIBUSB_1_0], + [Define if USB support is enabled via a libusb-1.0 compatible libusb]) +AC_CHECK_LIB([usb], [libusb_init], [have_libusb_1_0=yes]) +if test x$have_libusb_1_0 = xyes; then + case $target in + *-*-freebsd*) + # FreeBSD 8+ has a native libusb-1.0 API compatible + # library offered by -lusb (which is also libusb-0.1 + # compatible). FreeBSD <8 does not have a libusb-1.0 + # at all so probing will fail but we do not have to + # special-case that. + LIBUSB_1_0="-lusb" + ;; + *) + LIBUSB_1_0="-lusb-1.0" + ;; + esac + AC_DEFINE([HAVE_LIBUSB_1_0]) + AC_CHECK_HEADERS([libusb.h]) +fi +AC_SUBST(LIBUSB_1_0, $LIBUSB_1_0) +AH_TEMPLATE([HAVE_LIBFTDI], + [Define if FTDI support is enabled via libftdi]) +AC_CHECK_LIB([ftdi], [ftdi_init], [have_libftdi=yes], [], [-lusb]) +if test x$have_libftdi = xyes; then + LIBFTDI="-lftdi -lusb" + AC_DEFINE([HAVE_LIBFTDI]) +fi +AC_SUBST(LIBFTDI, $LIBFTDI) +# Checks for header files. +AC_CHECK_HEADERS([limits.h stdlib.h string.h]) +AC_CHECK_HEADERS([fcntl.h sys/ioctl.h sys/time.h termios.h unistd.h]) +AC_CHECK_HEADERS([ddk/hidsdi.h],,,[#include +#include ]) + + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_HEADER_TIME + +# Checks for library functions. +AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep]) + +AC_MSG_CHECKING([for a Win32 HID libray]) +SAVED_LIBS="${LIBS}" +case $target in + *-*-mingw32* | *-*-cygwin* | *-*-windows*) + LIBHID="-lhid -lsetupapi" + if test $ac_cv_header_ddk_hidsdi_h = yes + then + HIDINCLUDE="#include " + else + HIDINCLUDE="#include \"my_ddk_hidsdi.h\"" + fi + ;; + *) + LIBHID="" + ;; +esac +LIBS="${LIBS} ${LIBHID}" + +AH_TEMPLATE([HAVE_LIBHID], + [Define if HID support is enabled via the Win32 DDK]) +AC_TRY_RUN([#include +#include +$HIDINCLUDE + +int +main(void) +{ + GUID hidGuid; + HidD_GetHidGuid(&hidGuid); + + return 0; +} +], [have_libhid=yes], [have_libhid=no], [have_libhid=no]) +AC_MSG_RESULT([$have_libhid]) +if test x$have_libhid = xyes; then + AC_DEFINE([HAVE_LIBHID]) +else + LIBHID="" +fi +LIBS="${SAVED_LIBS}" +AC_SUBST(LIBHID, $LIBHID) + +# Check for types + +# Solaris has uint_t and ulong_t typedefs in , avoid +# the redeclaration in usbtiny.c. +AC_CHECK_TYPES([uint_t], [], [], [#include ]) +AC_CHECK_TYPES([ulong_t], [], [], [#include ]) + +# Checks for misc stuff. + +AC_ARG_ENABLE( + [versioned-doc], + AC_HELP_STRING( + [--enable-versioned-doc], + [install docs in directory with version name (default)]), + [case "${enableval}" in + yes) versioned_doc=yes ;; + no) versioned_doc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for versioned-doc option) ;; + esac], + [versioned_doc=yes]) + +if test "$versioned_doc" = "yes"; then + DOC_INST_DIR='$(DESTDIR)$(datadir)/doc/avrdude-$(VERSION)' +else + DOC_INST_DIR='$(DESTDIR)$(datadir)/doc/avrdude' +fi + +AC_ARG_ENABLE( + [doc], + AC_HELP_STRING( + [--enable-doc], + [Enable building documents]), + [case "${enableval}" in + yes) enabled_doc=yes ;; + no) enabled_doc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for disable-doc option) ;; + esac], + [enabled_doc=no]) + +AC_ARG_ENABLE( + [parport], + AC_HELP_STRING( + [--enable-parport], + [Enable accessing parallel ports(default)]), + [case "${enableval}" in + yes) enabled_parport=yes ;; + no) enabled_parport=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for enable-parport option) ;; + esac], + [enabled_parport=yes]) + +DIST_SUBDIRS_AC='doc windows' + +if test "$enabled_doc" = "yes"; then + SUBDIRS_AC='doc' +else + SUBDIRS_AC='' +fi + +AC_SUBST(DOC_INST_DIR, $DOC_INST_DIR) +AC_SUBST(SUBDIRS_AC, $SUBDIRS_AC) +AC_SUBST(DIST_SUBDIRS_AC, $DIST_SUBDIRS_AC) + + +# Find the parallel serial device files based on target system +# If a system doesn't have a PC style parallel, mark it as unknown. +case $target in + i[[3456]]86-*-linux*|x86_64-*-linux*) + DEFAULT_PAR_PORT="/dev/parport0" + DEFAULT_SER_PORT="/dev/ttyS0" + ;; + *-*-linux*) + DEFAULT_PAR_PORT="unknown" + DEFAULT_SER_PORT="/dev/ttyS0" + ;; + i[[3456]]86-*-*freebsd*|amd64-*-*freebsd*) + DEFAULT_PAR_PORT="/dev/ppi0" + DEFAULT_SER_PORT="/dev/cuad0" + ;; + *-*-*freebsd*) + DEFAULT_PAR_PORT="unknown" + DEFAULT_SER_PORT="/dev/cuad0" + ;; + *-*-solaris*) + DEFAULT_PAR_PORT="/dev/printers/0" + DEFAULT_SER_PORT="/dev/term/a" + ;; + *-*-msdos* | *-*-mingw32* | *-*-cygwin* | *-*-windows*) + DEFAULT_PAR_PORT="lpt1" + DEFAULT_SER_PORT="com1" + ;; + *) + DEFAULT_PAR_PORT="unknown" + DEFAULT_SER_PORT="unknown" + ;; +esac + +if test "$enabled_parport" = "yes"; then + AC_MSG_CHECKING([for parallel device]) + if test "$DEFAULT_PAR_PORT" = "unknown"; then + AC_MSG_NOTICE([parallel port access disabled for this system]) + enabled_parport=no + else + AC_MSG_RESULT([$DEFAULT_PAR_PORT]) + fi + AC_SUBST(DEFAULT_PAR_PORT, $DEFAULT_PAR_PORT) +fi + +AC_MSG_CHECKING([for serial device]) +AC_MSG_RESULT([$DEFAULT_SER_PORT]) +AC_SUBST(DEFAULT_SER_PORT, $DEFAULT_SER_PORT) + +if test "$enabled_parport" = "yes"; then + AC_DEFINE(HAVE_PARPORT, 1, [parallel port access enabled]) + confsubst="-e /^@HAVE_PARPORT_/d" +else + confsubst="-e /^@HAVE_PARPORT_BEGIN@/,/^@HAVE_PARPORT_END@/d" +fi +export confsubst + +# If we are compiling with gcc, enable all warning and make warnings errors. +if test "$GCC" = yes; then + ENABLE_WARNINGS="-Wall" + + # does this compiler support -Wno-pointer-sign ? + AC_MSG_CHECKING([if gcc accepts -Wno-pointer-sign ]) + + safe_CFLAGS=$CFLAGS + CFLAGS="$ENABLE_WARNINGS -Wno-pointer-sign" + + AC_TRY_COMPILE(, [ int main () { return 0 ; } ], [ + no_pointer_sign=yes + AC_MSG_RESULT([yes]) + ], [ + no_pointer_sign=no + AC_MSG_RESULT([no]) + ]) + CFLAGS=$safe_CFLAGS + + if test x$no_pointer_sign = xyes; then + ENABLE_WARNINGS="$ENABLE_WARNINGS -Wno-pointer-sign" + fi +fi +AC_SUBST(ENABLE_WARNINGS,$ENABLE_WARNINGS) + +# See if we need to drop into the windows subdir. +case $target in + *-*-mingw32* | *-*-cygwin* | *-*-windows*) + if test "$GCC" = yes -a \( "$CC" = "cc" -o "$CC" = "gcc" \); then + # does this compiler support -mno-cygwin? + AC_MSG_CHECKING([if $CC accepts -mno-cygwin]) + + safe_CFLAGS="$CFLAGS" + CFLAGS="$ENABLE_WARNINGS -mno-cygwin" + + AC_TRY_COMPILE(, [ int main () { return 0 ; } ], [ + no_cygwin=yes + AC_MSG_RESULT([yes]) + ], [ + no_cygwin=no + AC_MSG_RESULT([no]) + ]) + CFLAGS="$safe_CFLAGS" + + if test x$no_cygwin = xyes; then + CFLAGS="${CFLAGS} -mno-cygwin" + else + AC_MSG_NOTICE([Your compiler does not understand the -mno-cygwin option.]) + AC_MSG_NOTICE([You might want to select an alternative compiler, like]) + AC_MSG_NOTICE([]) + AC_MSG_NOTICE([CC=mingw32-gcc ./configure]) + AC_MSG_NOTICE([]) + fi + fi + + AC_MSG_CHECKING([if linker accepts -static]) + + safe_LDFLAGS="$LDFLAGS" + LDFLAGS="${LDFLAGS} -static" + AC_TRY_LINK(, [ int main () { return 0 ; } ], [ + can_link_static=yes + AC_MSG_RESULT([yes]) + ], [ + can_link_static_cygwin=no + AC_MSG_RESULT([no]) + ]) + LDFLAGS="$safe_LDFLAGS" + + if test x$can_link_static = xyes; then + LDFLAGS="${LDFLAGS} -static" + fi + + WINDOWS_DIRS="windows" + CFLAGS="${CFLAGS} -DWIN32NATIVE" + ;; +esac +AC_SUBST(WINDOWS_DIRS,$WINDOWS_DIRS) + +AC_CONFIG_FILES([ + doc/Makefile + windows/Makefile + avrdude.spec + Makefile +]) + +# The procedure to create avrdude.conf involves two steps. First, +# normal autoconf substitution will be applied, resulting in +# avrdude.conf.tmp. Finally, a sed command will be applied to filter +# out unwanted parts (currently the parallel port programmer types) +# based on previous configuration results, thereby producing the final +# avrdude.conf file. + +AC_CONFIG_FILES([avrdude.conf.tmp:avrdude.conf.in], + [sed $confsubst avrdude.conf.tmp > avrdude.conf]) + +AC_OUTPUT diff --git a/avrdude/confwin.c b/avrdude/confwin.c new file mode 100644 index 00000000..0ae373ae --- /dev/null +++ b/avrdude/confwin.c @@ -0,0 +1,54 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Eric B. Weddington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "avrdude.h" + +#if defined(WIN32NATIVE) + +#include +#include + + +static char *filename; + + +void win_sys_config_set(char sys_config[PATH_MAX]) +{ + sys_config[0] = 0; + + /* Use Windows API call to search for the Windows default system config file.*/ + SearchPath(NULL, "avrdude.conf", NULL, PATH_MAX, sys_config, &filename); + return; +} + + +void win_usr_config_set(char usr_config[PATH_MAX]) +{ + usr_config[0] = 0; + + /* Use Windows API call to search for the Windows default user config file. */ + SearchPath(NULL, "avrdude.rc", NULL, PATH_MAX, usr_config, &filename); + return; +} + + +#endif + + diff --git a/avrdude/confwin.h b/avrdude/confwin.h new file mode 100644 index 00000000..7ab33385 --- /dev/null +++ b/avrdude/confwin.h @@ -0,0 +1,40 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Eric B. Weddington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + +#if defined(WIN32NATIVE) +#ifndef confwin_h +#define confwin_h + +#ifdef __cplusplus +extern "C" { +#endif + +void win_sys_config_set(char sys_config[PATH_MAX]); +void win_usr_config_set(char usr_config[PATH_MAX]); + +#ifdef __cplusplus +} +#endif + +#endif +#endif + + diff --git a/avrdude/crc16.c b/avrdude/crc16.c new file mode 100644 index 00000000..0177c9da --- /dev/null +++ b/avrdude/crc16.c @@ -0,0 +1,83 @@ +/* + * Derived from CRC algorithm for JTAG ICE mkII, published in Atmel + * Appnote AVR067. Converted from C++ to C. + */ +#include "crc16.h" + +/* CRC16 Definitions */ +static const unsigned short crc_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* CRC calculation macros */ +#define CRC_INIT 0xFFFF +#define CRC(crcval,newchar) crcval = (crcval >> 8) ^ \ + crc_table[(crcval ^ newchar) & 0x00ff] + +unsigned short +crcsum(const unsigned char* message, unsigned long length, + unsigned short crc) +{ + unsigned long i; + + for(i = 0; i < length; i++) + { + CRC(crc, message[i]); + } + return crc; +} + +int +crcverify(const unsigned char* message, unsigned long length) +{ + /* + * Returns true if the last two bytes in a message is the crc of the + * preceding bytes. + */ + unsigned short expected; + + expected = crcsum(message, length - 2, CRC_INIT); + return (expected & 0xff) == message[length - 2] && + ((expected >> 8) & 0xff) == message[length - 1]; +} + +void +crcappend(unsigned char* message, unsigned long length) +{ + unsigned long crc; + + crc = crcsum(message, length, CRC_INIT); + message[length] = (unsigned char)(crc & 0xff); + message[length+1] = (unsigned char)((crc >> 8) & 0xff); +} diff --git a/avrdude/crc16.h b/avrdude/crc16.h new file mode 100644 index 00000000..db10131d --- /dev/null +++ b/avrdude/crc16.h @@ -0,0 +1,34 @@ +#ifndef CRC16_H +#define CRC16_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Derived from CRC algorithm for JTAG ICE mkII, published in Atmel + * Appnote AVR067. Converted from C++ to C. + */ + +extern unsigned short crcsum(const unsigned char* message, + unsigned long length, + unsigned short crc); +/* + * Verify that the last two bytes is a (LSB first) valid CRC of the + * message. + */ +extern int crcverify(const unsigned char* message, + unsigned long length); +/* + * Append a two byte CRC (LSB first) to message. length is size of + * message excluding crc. Space for the CRC bytes must be allocated + * in advance! + */ +extern void crcappend(unsigned char* message, + unsigned long length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/doc/.cvsignore b/avrdude/doc/.cvsignore new file mode 100644 index 00000000..ecbe8063 --- /dev/null +++ b/avrdude/doc/.cvsignore @@ -0,0 +1,22 @@ +.cvsignore +Makefile +Makefile.in +avrdude-html +avrdude.aux +avrdude.cp +avrdude.cps +avrdude.dvi +avrdude.fn +avrdude.info +avrdude.ky +avrdude.log +avrdude.pdf +avrdude.pg +avrdude.ps +avrdude.toc +avrdude.tp +avrdude.vr +mdate-sh +stamp-vti +texinfo.tex +version.texi diff --git a/avrdude/doc/Makefile.am b/avrdude/doc/Makefile.am new file mode 100644 index 00000000..c8c6634e --- /dev/null +++ b/avrdude/doc/Makefile.am @@ -0,0 +1,60 @@ +# +# avrdude - A Downloader/Uploader for AVR device programmers +# Copyright (C) 2003 Theodore A. Roth +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# $Id$ +# + +CLEANFILES = \ + version.texi \ + stamp-vti + +info_TEXINFOS = avrdude.texi + +all-local: info html ps pdf + +html: avrdude-html/avrdude.html + +avrdude-html/avrdude.html: $(srcdir)/$(info_TEXINFOS) + texi2html -split_node $(srcdir)/$(info_TEXINFOS) + if [ -e ./avrdude.html -o -e ./avrdude_1.html ]; then \ + mkdir -p avrdude-html ; \ + mv -f *.html avrdude-html ; \ + else \ + mv -f avrdude avrdude-html; \ + fi; + +clean-local: + rm -rf avrdude-html *.info + +install-data-local: install-docs + +install-docs: html ps pdf + $(mkinstalldirs) $(DOC_INST_DIR) + $(INSTALL_DATA) avrdude.ps $(DOC_INST_DIR)/avrdude.ps + $(INSTALL_DATA) avrdude.pdf $(DOC_INST_DIR)/avrdude.pdf + $(mkinstalldirs) $(DOC_INST_DIR)/avrdude-html + @list=`echo avrdude-html/*.html`; \ + for file in $$list; \ + do \ + $(INSTALL_DATA) $$file $(DOC_INST_DIR)/$$file; \ + done + +uninstall-local: + rm -rf $(DOC_INST_DIR) diff --git a/avrdude/doc/TODO b/avrdude/doc/TODO new file mode 100644 index 00000000..6c57c5ad --- /dev/null +++ b/avrdude/doc/TODO @@ -0,0 +1,26 @@ + +- Man page needs updated for avr910 info. + +- Website needs to link to docs: + http://savannah.nongnu.org/download/avrdude/doc/avrdude-html/ + +- Add "skip empty pages" optimization on avr910 paged write. The stk500 has + this optimization already. + +- Fix "overfull \hbox" issues in building documentation. + +- FIXME: term.c: terminal_get_input(): strip newlines in non-readline input + code. + +- FIXME: avr910.c: avr910_cmd(): Insert version check here. + +- FIXME: ser_posix.c: serial_close(): Should really restore the terminal to + original state here. + +- FIXME: main.c, par.c: exitspecs don't work if RESET-pin is controlled over + PPICTRL. + +- transfer ppi-speedtuning to the windows version (CAVEAT: This will make + programming too fast for chips with 500kHz clock) + +- make SCK-period configurable for PPI-programmers diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi new file mode 100644 index 00000000..4ea19bf5 --- /dev/null +++ b/avrdude/doc/avrdude.texi @@ -0,0 +1,2567 @@ +%% -*-texinfo-*- +\input texinfo + +@c $Id$ + +@setfilename avrdude.info +@settitle AVRDUDE +@finalout + +@include version.texi + +@c +@c These are set in version.texi which is automatically generated by automake. +@c +@c @set UPDATED 26 Febuary 2003 +@c @set EDITION 3.2.0 +@c @set VERSION 3.2.0 + +@c This is a dir.info fragment to support semi-automated addition of +@c manuals to an info tree. +@dircategory AVR Programming & development tools. +@direntry +* AvrDude: (avrdude). AVR program downloader/uploader. +@end direntry + +@ifinfo +This file documents the avrdude program. + +For avrdude version @value{VERSION}, @value{UPDATED}. + +Copyright @copyright{} 2003, 2005 Brian Dean + +Copyright @copyright{} 2006 - 2011 J@"org Wunsch + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Free Software Foundation. + +Alternatively, this documentation may be copied and distributed under +the terms of the GNU Free Documentation License (FDL), version 1.3. +@end ifinfo + +@titlepage +@title AVRDUDE +@subtitle A program for download/uploading AVR microcontroller flash and eeprom. +@subtitle For AVRDUDE, Version @value{VERSION}, @value{UPDATED}. +@author by Brian S. Dean + +@page +Send comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}. + +Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs. + +Copyright @copyright{} 2003,2005 Brian S. Dean + +Copyright @copyright{} 2006 - 2008 J@"org Wunsch +@sp 2 + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Free Software Foundation. +@end titlepage + +@contents + +@c +@c Top Node +@c +@node Top, Introduction, (dir), (dir) +@comment node-name, next, previous, up + +@ifinfo +This file documents the avrdude program for downloading/uploading +programs to Atmel AVR microcontrollers. + +For avrdude version @value{VERSION}, @value{UPDATED}. + +Send comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}. + +Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs. + +Copyright @copyright{} 2003,2005 Brian S. Dean + +Copyright @copyright{} 2006 J@"org Wunsch +@end ifinfo + +@menu +* Introduction:: +* Command Line Options:: +* Terminal Mode Operation:: +* Configuration File:: +* Programmer Specific Information:: +* Platform Dependent Information:: +* Troubleshooting:: +@end menu + +@c +@c Node +@c +@node Introduction, Command Line Options, Top, Top +@comment node-name, next, previous, up +@chapter Introduction +@cindex introduction + +AVRDUDE - AVR Downloader Uploader - is a program for downloading and +uploading the on-chip memories of Atmel's AVR microcontrollers. It can +program the Flash and EEPROM, and where supported by the serial +programming protocol, it can program fuse and lock bits. AVRDUDE also +supplies a direct instruction mode allowing one to issue any programming +instruction to the AVR chip regardless of whether AVRDUDE implements +that specific feature of a particular chip. + +AVRDUDE can be used effectively via the command line to read or write +all chip memory types (eeprom, flash, fuse bits, lock bits, signature +bytes) or via an interactive (terminal) mode. Using AVRDUDE from the +command line works well for programming the entire memory of the chip +from the contents of a file, while interactive mode is useful for +exploring memory contents, modifying individual bytes of eeprom, +programming fuse/lock bits, etc. + +AVRDUDE supports the following basic programmer types: Atmel's STK500, +Atmel's AVRISP and AVRISP mkII devices, +Atmel's STK600, +Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode), appnote +avr910, appnote avr109 (including the AVR Butterfly), +serial bit-bang adapters, +and the PPI (parallel port interface). PPI represents a class +of simple programmers where the programming lines are directly +connected to the PC parallel port. Several pin configurations exist +for several variations of the PPI programmers, and AVRDUDE can be be +configured to work with them by either specifying the appropriate +programmer on the command line or by creating a new entry in its +configuration file. All that's usually required for a new entry is to +tell AVRDUDE which pins to use for each programming function. + +A number of equally simple bit-bang programming adapters that connect +to a serial port are supported as well, among them the popular +Ponyprog serial adapter, and the DASA and DASA3 adapters that used to +be supported by uisp(1). Note that these adapters are meant to be +attached to a physical serial port. Connecting to a serial port +emulated on top of USB is likely to not work at all, or to work +abysmally slow. + +The STK500, JTAG ICE, avr910, and avr109/butterfly use the serial port to communicate with the PC. +The STK600, JTAG ICE mkII, AVRISP mkII, USBasp, avrftdi (and derivitives), and USBtinyISP +programmers communicate through the USB, using @code{libusb} as a +platform abstraction layer. +The avrftdi adds support for the FT2232C/D, FT2232H, and FT4232H devices. These all use +the MPSSE mode, which has a specific pin mapping. Bit 1 (the lsb of the byte in the config +file) is SCK. Bit 2 is MOSI, and Bit 3 is MISO. Bit 4 usually reset. The 2232C/D parts +are only supported on interface A, but the H parts can be either A or B (specified by the +usbdev config parameter). +The STK500, STK600, JTAG ICE, and avr910 contain on-board logic to control the programming of the target +device. +The avr109 bootloader implements a protocol similar to avr910, but is +actually implemented in the boot area of the target's flash ROM, as +opposed to being an external device. +The fundamental difference between the two types lies in the +protocol used to control the programmer. The avr910 protocol is very +simplistic and can easily be used as the basis for a simple, home made +programmer since the firmware is available online. On the other hand, +the STK500 protocol is more robust and complicated and the firmware is +not openly available. +The JTAG ICE also uses a serial communication protocol which is similar +to the STK500 firmware version 2 one. However, as the JTAG ICE is +intended to allow on-chip debugging as well as memory programming, the +protocol is more sophisticated. +(The JTAG ICE mkII protocol can also be run on top of USB.) +Only the memory programming functionality of the JTAG ICE is supported +by AVRDUDE. +For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported, provided +it has a firmware revision of at least 4.14 (decimal). +See below for the limitations of debugWire. +For ATxmega devices, the JTAG ICE mkII is supported in PDI mode, provided it +has a revision 1 hardware and firmware version of at least 5.37 (decimal). + +The AVR Dragon is supported in all modes (ISP, JTAG, PDI, HVSP, PP, debugWire). +When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a +JTAG ICE mkII, so all device-specific comments for that device +will apply as well. +When used in ISP and PDI mode, the AVR Dragon behaves similar to an +AVRISP mkII (or JTAG ICE mkII in ISP mode), so all device-specific +comments will apply there. +In particular, the Dragon starts out with a rather fast ISP clock +frequency, so the @code{-B @var{bitclock}} +option might be required to achieve a stable ISP communication. +For ATxmega devices, the AVR Dragon is supported in PDI mode, provided it +has a firmware version of at least 6.11 (decimal). + +Wiring boards are supported, utilizing STK500 V2.x protocol, but +a simple DTR/RTS toggle to set the boards into programming mode. +The programmer type is ``wiring''. + +The Arduino (which is very similar to the STK500 1.x) is supported via +its own programmer type specification ``arduino''. + +The BusPirate is a versatile tool that can also be used as an AVR programmer. +A single BusPirate can be connected to up to 3 independent AVRs. See +the section on +@emph{extended parameters} +below for details. + +The USBasp ISP and USBtinyISP adapters are also supported, provided AVRDUDE +has been compiled with libusb support. +They both feature simple firmware-only USB implementations, running on +an ATmega8 (or ATmega88), or ATtiny2313, respectively. + + +@menu +* History:: +@end menu + +@c +@c Node +@c +@node History, , Introduction, Introduction +@section History and Credits + +AVRDUDE was written by Brian S. Dean under the name of AVRPROG to run on +the FreeBSD Operating System. Brian renamed the software to be called +AVRDUDE when interest grew in a Windows port of the software so that the +name did not conflict with AVRPROG.EXE which is the name of Atmel's +Windows programming software. + +The AVRDUDE source now resides in the public CVS repository on +savannah.gnu.org (@url{http://savannah.gnu.org/projects/avrdude/}), +where it continues to be enhanced and ported to other systems. In +addition to FreeBSD, AVRDUDE now runs on Linux and Windows. The +developers behind the porting effort primarily were Ted Roth, Eric +Weddington, and Joerg Wunsch. + +And in the spirit of many open source projects, this manual also draws +on the work of others. The initial revision was composed of parts of +the original Unix manual page written by Joerg Wunsch, the original web +site documentation by Brian Dean, and from the comments describing the +fields in the AVRDUDE configuration file by Brian Dean. The texi +formatting was modeled after that of the Simulavr documentation by Ted +Roth. + + +@c +@c Node +@c +@node Command Line Options, Terminal Mode Operation, Introduction, Top +@chapter Command Line Options +@cindex options + +@menu +* Option Descriptions:: +* Programmers accepting extended parameters:: +* Example Command Line Invocations:: +@end menu + +@c +@c Node +@c +@node Option Descriptions, Programmers accepting extended parameters, Command Line Options, Command Line Options +@section Option Descriptions + +@noindent +AVRDUDE is a command line tool, used as follows: + +@smallexample +avrdude -p partno @var{options} @dots{} +@end smallexample + +@noindent +Command line options are used to control AVRDUDE's behaviour. The +following options are recognized: + +@table @code +@item -p @var{partno} +This is the only mandatory option and it tells AVRDUDE what type of part +(MCU) that is connected to the programmer. The @var{partno} parameter +is the part's id listed in the configuration file. Specify -p ? to list +all parts in the configuration file. If a part is unknown +to AVRDUDE, it means that there is no config file entry for that part, +but it can be added to the configuration file if you have the Atmel +datasheet so that you can enter the programming specifications. +Currently, the following MCU types are understood: + +@multitable @columnfractions .15 .3 +@item @code{1200} @tab AT90S1200 +@item @code{2313} @tab AT90S2313 +@item @code{2333} @tab AT90S2333 +@item @code{2343} @tab AT90S2343 (*) +@item @code{4414} @tab AT90S4414 +@item @code{4433} @tab AT90S4433 +@item @code{4434} @tab AT90S4434 +@item @code{8515} @tab AT90S8515 +@item @code{8535} @tab AT90S8535 +@item @code{c128} @tab AT90CAN128 +@item @code{c32} @tab AT90CAN32 +@item @code{c64} @tab AT90CAN64 +@item @code{m103} @tab ATmega103 +@item @code{m128} @tab ATmega128 +@item @code{m1280} @tab ATmega1280 +@item @code{m1281} @tab ATmega1281 +@item @code{m1284p} @tab ATmega1284P +@item @code{m128rfa1} @tab ATmega128RFA1 +@item @code{m16} @tab ATmega16 +@item @code{m161} @tab ATmega161 +@item @code{m162} @tab ATmega162 +@item @code{m163} @tab ATmega163 +@item @code{m164} @tab ATmega164 +@item @code{m164p} @tab ATmega164P +@item @code{m168} @tab ATmega168 +@item @code{m168p} @tab ATmega168P +@item @code{m169} @tab ATmega169 +@item @code{m16u2} @tab ATmega16U2 +@item @code{m2560} @tab ATmega2560 (**) +@item @code{m2561} @tab ATmega2561 (**) +@item @code{m32} @tab ATmega32 +@item @code{m324p} @tab ATmega324P +@item @code{m325} @tab ATmega325 +@item @code{m3250} @tab ATmega3250 +@item @code{m328p} @tab ATmega328P +@item @code{m329} @tab ATmega329 +@item @code{m3290} @tab ATmega3290 +@item @code{m329p} @tab ATmega329P +@item @code{m3290p} @tab ATmega3290P +@item @code{m32u2} @tab ATmega32U2 +@item @code{m32u4} @tab ATmega32U4 +@item @code{m48} @tab ATmega48 +@item @code{m64} @tab ATmega64 +@item @code{m640} @tab ATmega640 +@item @code{m644p} @tab ATmega644P +@item @code{m644} @tab ATmega644 +@item @code{m645} @tab ATmega645 +@item @code{m6450} @tab ATmega6450 +@item @code{m649} @tab ATmega649 +@item @code{m6490} @tab ATmega6490 +@item @code{m8} @tab ATmega8 +@item @code{m8515} @tab ATmega8515 +@item @code{m8535} @tab ATmega8535 +@item @code{m88} @tab ATmega88 +@item @code{m88p} @tab ATmega88P +@item @code{m8u2} @tab ATmega8U2 +@item @code{pwm2} @tab AT90PWM2 +@item @code{pwm2b} @tab AT90PWM2B +@item @code{pwm3} @tab AT90PWM3 +@item @code{pwm3b} @tab AT90PWM3B +@item @code{t10} @tab ATtiny10 +@item @code{t12} @tab ATtiny12 (***) +@item @code{t13} @tab ATtiny13 +@item @code{t15} @tab ATtiny15 +@item @code{t2313} @tab ATtiny2313 +@item @code{t25} @tab ATtiny25 +@item @code{t26} @tab ATtiny26 +@item @code{t261} @tab ATtiny261 +@item @code{t4} @tab ATtiny4 +@item @code{t4313} @tab ATtiny4313 +@item @code{t44} @tab ATtiny44 +@item @code{t45} @tab ATtiny45 +@item @code{t461} @tab ATtiny461 +@item @code{t5} @tab ATtiny5 +@item @code{t84} @tab ATtiny84 +@item @code{t85} @tab ATtiny85 +@item @code{t861} @tab ATtiny861 +@item @code{t88} @tab ATtiny88 +@item @code{t9} @tab ATtiny9 +@item @code{ucr2} @tab AT32uca0512 +@item @code{usb1286} @tab ATmega1286 +@item @code{usb1287} @tab ATmega1287 +@item @code{usb162} @tab ATmega162 +@item @code{usb646} @tab ATmega647 +@item @code{usb647} @tab ATmega647 +@item @code{usb82} @tab ATmega82 +@item @code{x128a1} @tab ATxmega128A1 +@item @code{x128a1d} @tab ATxmega128A1revD +@item @code{x128a3} @tab ATxmega128A3 +@item @code{x128a4} @tab ATxmega128A4 +@item @code{x16a4} @tab ATxmega16A4 +@item @code{x192a1} @tab ATxmega192A1 +@item @code{x192a3} @tab ATxmega192A3 +@item @code{x256a1} @tab ATxmega256A1 +@item @code{x256a3} @tab ATxmega256A3 +@item @code{x256a3b} @tab ATxmega256A3B +@item @code{x32a4} @tab ATxmega32A4 +@item @code{x64a1} @tab ATxmega64A1 +@item @code{x64a3} @tab ATxmega64A3 +@item @code{x64a4} @tab ATxmega64A4 +@end multitable + +(*) The AT90S2323 and ATtiny22 use the same algorithm. + +(**) Flash addressing above 128 KB is not supported by all +programming hardware. Known to work are jtag2, stk500v2, +and bit-bang programmers. + +(***) +The ATtiny11 uses the same algorithm, but can only be +programmed in high-voltage serial mode. + +@item -b @var{baudrate} +Override the RS-232 connection baud rate specified in the respective +programmer's entry of the configuration file. + +@item -B @var{bitclock} +Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only). +The value is a floating-point number in microseconds. +The default value of the JTAG ICE results in about 1 microsecond bit +clock period, suitable for target MCUs running at 4 MHz clock and +above. +Unlike certain parameters in the STK500, the JTAG ICE resets all its +parameters to default values when the programming software signs +off from the ICE, so for MCUs running at lower clock speeds, this +parameter must be specified on the command-line. +It can also be set in the configuration file by using the 'default_bitclock' +keyword. + +@item -c @var{programmer-id} +Specify the programmer to be used. AVRDUDE knows about several common +programmers. Use this option to specify which one to use. The +@var{programmer-id} parameter is the programmer's id listed in the +configuration file. Specify -c ? to list all programmers in the +configuration file. If you have a programmer that is unknown to +AVRDUDE, and the programmer is controlled via the PC parallel port, +there's a good chance that it can be easily added to the configuration +file without any code changes to AVRDUDE. Simply copy an existing entry +and change the pin definitions to match that of the unknown programmer. +Currently, the following programmer ids are understood and supported: + +@multitable @columnfractions .2 .6 +@item @code{2232HIO} @tab +FT2232H based generic programmer +@item @code{89isp} @tab +Atmel at89isp cable +@item @code{abcmini} @tab +ABCmini Board, aka Dick Smith HOTCHIP +@item @code{alf} @tab +Nightshade ALF-PgmAVR,@* +@url{http://nightshade.homeip.net/} +@item @code{arduino} +Arduino board, protocol similar to STK500 1.x +@item @code{atisp} @tab +AT-ISP V1.1 programming cable for AVR-SDK1 from,@* +@url{http://micro-research.co.th/} +@item @code{avr109} @tab +Atmel AppNote AVR109 Boot Loader +@item @code{avr910} @tab +Atmel Low Cost Serial Programmer +@item @code{avr911} @tab +Atmel AppNote AVR911 AVROSP (an alias for avr109) +@item @code{avrftdi} @tab +FT2232D based generic programmer +@item @code{avrisp} @tab +Atmel AVR ISP (an alias for stk500) +@item @code{avrisp2} @tab +Atmel AVR ISP mkII in ISP mode, in PDI mode for ATxmega devices, or +in TPI mode for ATtiny4/5/9/10 +@item @code{avrispmkII} @tab +Atmel AVR ISP mkII (alias for stk500v2) +@item @code{avrispv2} @tab +Atmel AVR ISP, running a version 2.x firmware (an alias for stk500v2) +@item @code{bascom} @tab +Bascom SAMPLE programming cable +@item @code{blaster} @tab +Altera ByteBlaster +@item @code{bsd} @tab +Brian Dean's Programmer,@* +@url{http://www.bsdhome.com/avrdude/} +@item @code{buspirate} @tab +The Bus Pirate +@item @code{butterfly} @tab +Atmel Butterfly Development Board +@item @code{c2n232i} @tab +C2N232I, reset=dtr sck=!rts mosi=!txd miso=!cts,@* +@url{http://www.ktverkko.fi/~msmakela/8bit/c2n232/hardware/index.en.html} +@item @code{dapa} @tab +Direct AVR Parallel Access cable +@item @code{dasa} @tab +serial port banging, reset=rts sck=dtr mosi=txd miso=cts +@item @code{dasa3} @tab +serial port banging, reset=!dtr sck=rts mosi=txd miso=cts +@item @code{dragon_dw} @tab +AVR Dragon in debugWire mode +@item @code{dragon_hvsp} @tab +AVR Dragon in high-voltage serial programming mode +@item @code{dragon_isp} @tab +AVR Dragon in ISP mode +@item @code{dragon_jtag} @tab +AVR Dragon in JTAG mode +@item @code{dragon_pdi} @tab +AVR Dragon in PDI mode +@item @code{dragon_pp} @tab +AVR Dragon in (high-voltage) parallel programming mode +@item @code{dt006} @tab +Dontronics DT006 +@item @code{ere-isp-avr} @tab +ERE ISP-AVR,@* +@url{http://www.ere.co.th/download/sch050713.pdf} +@item @code{frank-stk200}@tab +Frank's STK200 clone,@* +@url{http://electropol.free.fr/spip/spip.php?article15} +@item @code{futurlec} @tab +Futurlec.com programming cable +@item @code{jtag1} @tab +Atmel JTAG ICE mkI, running at 115200 Bd +@item @code{jtag1slow} @tab +Atmel JTAG ICE mkI, running at 19200 Bd +@item @code{jtag2} @tab +Atmel JTAG ICE mkII, running at 115200 Bd +@item @code{jtag2avr32} @tab +Atmel JTAG ICE mkII in AVR32 mode. +@item @code{jtag2dw} @tab +Atmel JTAG ICE mkII in debugWire mode. +@item @code{jtag2fast} @tab +Atmel JTAG ICE mkII, running at 115200 Bd +@item @code{jtag2isp} @tab +Atmel JTAG ICE mkII in ISP mode. +@item @code{jtag2pdi} @tab +Atmel JTAG ICE mkII in PDI mode. +@item @code{jtag2slow} @tab +Atmel JTAG ICE mkII (default speed 19200 Bd) +@item @code{jtagmkI} @tab +Atmel JTAG ICE mkI, running at 115200 Bd +@item @code{jtagmkII} @tab +Atmel JTAG ICE mkII (default speed 19200 Bd) +@item @code{jtagmkII_avr32} @tab +Atmel JTAG ICE mkII in AVR32 mode. +@item @code{mib510} @tab +Crossbow MIB510 programming board +@item @code{pavr} @tab +Jason Kyle's pAVR Serial Programmer +@item @code{picoweb} @tab +Picoweb Programming Cable,@* +@url{http://www.picoweb.net/} +@item @code{pony-stk200} @tab +Pony Prog STK200 +@item @code{ponyser} @tab +design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts +@item @code{siprog} @tab +Lancos SI-Prog,@* +@url{http://www.lancos.com/siprogsch.html} +@item @code{sp12} @tab +Steve Bolt's Programmer +@item @code{stk200} @tab +STK200 +@item @code{stk500} @tab +Atmel STK500, probing for either version 1.x or 2.x firmware +@item @code{stk500hvsp} @tab +Atmel STK500 in high-voltage serial programming mode(version 2.x firmware only) +@item @code{stk500pp} @tab +Atmel STK500 in parallel programming mode (version 2.xfirmware only) +@item @code{stk500v1} @tab +Atmel STK500, running a version 1.x firmware +@item @code{stk500v2} @tab +Atmel STK500, running a version 2.x firmware +@item @code{stk600} @tab +Atmel STK600 in ISP mode, in PDI mode for ATxmega devices, or +in TPI mode for ATtiny4/5/9/10 +@item @code{stk600hvsp} @tab +Atmel STK600 in high-voltage serial programming mode +@item @code{stk600pp} @tab +Atmel STK600 in parallel programming mode +@item @code{usbasp} @tab +USBasp,@* +@url{http://www.fischl.de/usbasp/} +@item @code{usbtiny} @tab +USBtiny simple USB programmer,@* +@url{http://www.ladyada.net/make/usbtinyisp/} +@item @code{wiring} @tab +Wiring board, utilizing STK500 V2.x protocol,@* +@url{http://wiring.org.co/} +@item @code{xil} @tab +Xilinx JTAG cable +@end multitable + + + +@item -C @var{config-file} +Use the specified config file for configuration data. This file +contains all programmer and part definitions that AVRDUDE knows about. +If you have a programmer or part that AVRDUDE does not know about, you +can add it to the config file (be sure and submit a patch back to the +author so that it can be incorporated for the next version). If not +specified, AVRDUDE reads the configuration file from +/usr/local/etc/avrdude.conf (FreeBSD and Linux). See Appendix A for +the method of searching for the configuration file for Windows. + +@item -D +Disable auto erase for flash. When the -U option with flash memory is +specified, avrdude will perform a chip erase before starting any of the +programming operations, since it generally is a mistake to program the flash +without performing an erase first. This option disables that. +Auto erase is not used for ATxmega devices as these devices can +use page erase before writing each page so no explicit chip erase +is required. +Note however that any page not affected by the current operation +will retain its previous contents. + +@item -e +Causes a chip erase to be executed. This will reset the contents of the +flash ROM and EEPROM to the value `0xff', and clear all lock bits. +Except for ATxmega devices which can use page erase, +it is basically a +prerequisite command before the flash ROM can be reprogrammed again. +The only exception would be if the new contents would exclusively cause +bits to be programmed from the value `1' to `0'. Note that in order +to reprogram EERPOM cells, no explicit prior chip erase is required +since the MCU provides an auto-erase cycle in that case before +programming the cell. + + +@item -E @var{exitspec}[,@dots{}] +By default, AVRDUDE leaves the parallel port in the same state at exit +as it has been found at startup. This option modifies the state of the +`/RESET' and `Vcc' lines the parallel port is left at, according to +the exitspec arguments provided, as follows: + +@table @code +@itemx reset +The `/RESET' signal will be left activated at program exit, that is it +will be held low, in order to keep the MCU in reset state afterwards. +Note in particular that the programming algorithm for the AT90S1200 +device mandates that the `/RESET' signal is active before powering up +the MCU, so in case an external power supply is used for this MCU type, +a previous invocation of AVRDUDE with this option specified is one of +the possible ways to guarantee this condition. + +@itemx noreset +The `/RESET' line will be deactivated at program exit, thus allowing the +MCU target program to run while the programming hardware remains +connected. + +@itemx vcc +This option will leave those parallel port pins active (i. e. high) that +can be used to supply `Vcc' power to the MCU. + +@itemx novcc +This option will pull the `Vcc' pins of the parallel port down at +program exit. + +@itemx d_high +This option will leave the 8 data pins on the parallel port active +(i. e. high). + +@itemx d_low +This option will leave the 8 data pins on the parallel port inactive +(i. e. low). + +@end table + +Multiple @var{exitspec} arguments can be separated with commas. + + +@item -F +Normally, AVRDUDE tries to verify that the device signature read from +the part is reasonable before continuing. Since it can happen from time +to time that a device has a broken (erased or overwritten) device +signature but is otherwise operating normally, this options is provided +to override the check. +Also, for programmers like the Atmel STK500 and STK600 which can +adjust parameters local to the programming tool (independent of an +actual connection to a target controller), this option can be used +together with @option{-t} to continue in terminal mode. + +@item -i @var{delay} +For bitbang-type programmers, delay for approximately +@var{delay} +microseconds between each bit state change. +If the host system is very fast, or the target runs off a slow clock +(like a 32 kHz crystal, or the 128 kHz internal RC oscillator), this +can become necessary to satisfy the requirement that the ISP clock +frequency must not be higher than 1/4 of the CPU clock frequency. +This is implemented as a spin-loop delay to allow even for very +short delays. +On Unix-style operating systems, the spin loop is initially calibrated +against a system timer, so the number of microseconds might be rather +realistic, assuming a constant system load while AVRDUDE is running. +On Win32 operating systems, a preconfigured number of cycles per +microsecond is assumed that might be off a bit for very fast or very +slow machines. + +@item -n +No-write - disables actually writing data to the MCU (useful for +debugging AVRDUDE). + +@item -O +Perform a RC oscillator run-time calibration according to Atmel +application note AVR053. +This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII +hardware. +Note that the result will be stored in the EEPROM cell at address 0. + +@item -P @var{port} +Use port to identify the device to which the programmer is attached. +Normally, the default parallel port is used, but if the programmer type +normally connects to the serial port, the default serial port will be +used. See Appendix A, Platform Dependent Information, to find out the +default port names for your platform. If you need to use a different +parallel or serial port, use this option to specify the alternate port name. + +On Win32 operating systems, the parallel ports are referred to as lpt1 +through lpt3, referring to the addresses 0x378, 0x278, and 0x3BC, +respectively. If the parallel port can be accessed through a different +address, this address can be specified directly, using the common C +language notation (i. e., hexadecimal values are prefixed by @var{0x}). + +For the JTAG ICE mkII, if AVRDUDE has been built with libusb support, +@var{port} may alternatively be specified as +@code{usb}[:@var{serialno}]. In that case, the JTAG ICE mkII will be +looked up on USB. If @var{serialno} is also specified, it will be +matched against the serial number read from any JTAG ICE mkII found on +USB. The match is done after stripping any existing colons from the +given serial number, and right-to-left, so only the least significant +bytes from the serial number need to be given. +For a trick how to find out the serial numbers of all JTAG ICEs +attached to USB, see @ref{Example Command Line Invocations}. + +As the AVRISP mkII device can only be talked to over USB, the very +same method of specifying the port is required there. + +For the USB programmer "AVR-Doper" running in HID mode, the port must +be specified as @var{avrdoper}. Libusb support is required on Unix +but not on Windows. For more information about AVR-Doper see +@url{http://www.obdev.at/avrusb/avrdoper.html}. + +For the USBtinyISP, which is a simplicistic device not implementing +serial numbers, multiple devices can be distinguished by their +location in the USB hierarchy. +@xref{Troubleshooting} for examples. + +For programmers that attach to a serial port using some kind of +higher level protocol (as opposed to bit-bang style programmers), +@var{port} can be specified as @code{net}:@var{host}:@var{port}. +In this case, instead of trying to open a local device, a TCP +network connection to (TCP) @var{port} on @var{host} +is established. +The remote endpoint is assumed to be a terminal or console server +that connects the network stream to a local serial port where the +actual programmer has been attached to. +The port is assumed to be properly configured, for example using a +transparent 8-bit data connection without parity at 115200 Baud +for a STK500. + +@emph{This feature is currently not implemented for Win32 systems.} + + +@item -q +Disable (or quell) output of the progress bar while reading or writing +to the device. Specify it a second time for even quieter operation. + +@item -u +Disables the default behaviour of reading out the fuses three times before +programming, then verifying at the end of programming that the fuses have not +changed. If you want to change fuses you will need to specify this option, +as avrdude will see the fuses have changed (even though you wanted to) and +will change them back for your "safety". This option was designed to +prevent cases of fuse bits magically changing (usually called @emph{safemode}). + +@item -t +Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up- +or downloading files. See below for a detailed description of the +terminal mode. + +@item -U @var{memtype}:@var{op}:@var{filename}[:@var{format}] +Perform a memory operation. +Multiple @option{-U} options can be specified in order to operate on +multiple memories on the same command-line invocation. The +@var{memtype} field specifies the memory type to operate on. Use +the @option{-v} option on the command line or the @code{part} command from +terminal mode to display all the memory types supported by a particular +device. +Typically, a device's memory configuration at least contains +the memory types +@code{flash} +and +@code{eeprom}. +All memory types currently known are: +@table @code +@item calibration +One or more bytes of RC oscillator calibration data. +@item eeprom +The EEPROM of the device. +@item efuse +The extended fuse byte. +@item flash +The flash ROM of the device. +@item fuse +The fuse byte in devices that have only a single fuse byte. +@item hfuse +The high fuse byte. +@item lfuse +The low fuse byte. +@item lock +The lock byte. +@item signature +The three device signature bytes (device ID). +@item fuse@emph{N} +The fuse bytes of ATxmega devices, @emph{N} is an integer number +for each fuse supported by the device. +@item application +The application flash area of ATxmega devices. +@item apptable +The application table flash area of ATxmega devices. +@item boot +The boot flash area of ATxmega devices. +@item prodsig +The production signature (calibration) area of ATxmega devices. +@item usersig +The user signature area of ATxmega devices. +@end table + +The @var{op} field specifies what operation to perform: + +@table @code +@itemx r +read the specified device memory and write to the specified file + +@itemx w +read the specified file and write it to the specified device memory + +@itemx v +read the specified device memory and the specified file and perform a verify operation + +@end table + +The @var{filename} field indicates the name of the file to read or +write. The @var{format} field is optional and contains the format of +the file to read or write. Possible values are: + +@table @code +@itemx i +Intel Hex + +@itemx s +Motorola S-record + +@itemx r +raw binary; little-endian byte order, in the case of the flash ROM data + +@itemx m +immediate mode; actual byte values specified on the command line, +separated by commas or spaces in place of the @var{filename} field of +the @option{-U} option. This is useful +for programming fuse bytes without having to create a single-byte file +or enter terminal mode. If the number specified begins with @code{0x}, +it is treated as a hex value. If the number otherwise begins with a +leading zero (@code{0}) it is treated as octal. Otherwise, the value is +treated as decimal. + +@itemx a +auto detect; valid for input only, and only if the input is not provided +at stdin. + +@itemx d +decimal; this and the following formats are only valid on output. +They generate one line of output for the respective memory section, +forming a comma-separated list of the values. +This can be particularly useful for subsequent processing, like for +fuse bit settings. + +@itemx h +hexadecimal; each value will get the string @emph{0x} prepended. + +@itemx o +octal; each value will get a @emph{0} +prepended unless it is less than 8 in which case it gets no prefix. + +@itemx b +binary; each value will get the string @emph{0b} prepended. + +@end table + +The default is to use auto detection for input files, and raw binary +format for output files. + +Note that if @var{filename} contains a colon, the @var{format} field is +no longer optional since the filename part following the colon would +otherwise be misinterpreted as @var{format}. + +As an abbreviation, the form @code{-U} @var{filename} +is equivalent to specifying +@code{-U} @emph{flash:w:}@var{filename}@emph{:a}. +This will only work if @var{filename} does not have a colon in it. + +@item -v +Enable verbose output. + +@item -V +Disable automatic verify check when uploading data. + +@item -x @var{extended_param} +Pass @var{extended_param} to the chosen programmer implementation as +an extended parameter. The interpretation of the extended parameter +depends on the programmer itself. See below for a list of programmers +accepting extended parameters. + +@item -y +Tells AVRDUDE to use the last four bytes of the connected parts' EEPROM +memory to track the number of times the device has been erased. When +this option is used and the @option{-e} flag is specified to generate a +chip erase, the previous counter will be saved before the chip erase, it +is then incremented, and written back after the erase cycle completes. +Presumably, the device would only be erased just before being +programmed, and thus, this can be utilized to give an indication of how +many erase-rewrite cycles the part has undergone. Since the FLASH +memory can only endure a finite number of erase-rewrite cycles, one can +use this option to track when a part is nearing the limit. The typical +limit for Atmel AVR FLASH is 1000 cycles. Of course, if the +application needs the last four bytes of EEPROM memory, this option +should not be used. + +@item -Y @var{cycles} +Instructs AVRDUDE to initialize the erase-rewrite cycle counter residing +at the last four bytes of EEPROM memory to the specified value. If the +application needs the last four bytes of EEPROM memory, this option +should not be used. + +@end table + +@page +@c +@c Node +@c +@node Programmers accepting extended parameters, Example Command Line Invocations, Option Descriptions, Command Line Options +@section Programmers accepting extended parameters + +@table @code + +@item JTAG ICE mkII +@itemx AVR Dragon + +When using the JTAG ICE mkII or AVR Dragon in JTAG mode, the +following extended parameter is accepted: +@table @code +@item @samp{jtagchain=UB,UA,BB,BA} +Setup the JTAG scan chain for @var{UB} units before, @var{UA} units +after, @var{BB} bits before, and @var{BA} bits after the target AVR, +respectively. +Each AVR unit within the chain shifts by 4 bits. +Other JTAG units might require a different bit shift count. +@end table + +@item AVR910 + +The AVR910 programmer type accepts the following extended parameter: +@table @code +@item @samp{devcode=VALUE} +Override the device code selection by using @var{VALUE} +as the device code. +The programmer is not queried for the list of supported +device codes, and the specified @var{VALUE} +is not verified but used directly within the +@code{T} command sent to the programmer. +@var{VALUE} can be specified using the conventional number notation of the +C programming language. +@item @samp{no_blockmode} +Disables the default checking for block transfer capability. +Use +@samp{no_blockmode} only if your @samp{AVR910} +programmer creates errors during initial sequence. +@end table + +@item BusPirate + +The BusPirate programmer type accepts the following extended parameters: +@table @code +@item @samp{reset=cs,aux,aux2} +The default setup assumes the BusPirate's CS output pin connected to +the RESET pin on AVR side. It is however possible to have multiple AVRs +connected to the same BP with MISO, MOSI and SCK lines common for all of them. +In such a case one AVR should have its RESET connected to BusPirate's +@emph{CS} +pin, second AVR's RESET connected to BusPirate's +@emph{AUX} +pin and if your BusPirate has an +@emph{AUX2} +pin (only available on BusPirate version v1a with firmware 3.0 or newer) +use that to activate RESET on the third AVR. + +It may be a good idea to decouple the BusPirate and the AVR's SPI buses from +each other using a 3-state bus buffer. For example 74HC125 or 74HC244 are some +good candidates with the latches driven by the appropriate reset pin (cs, +aux or aux2). Otherwise the SPI traffic in one active circuit may interfere +with programming the AVR in the other design. + +@item @samp{speed=@var{0..7}} +@table @code +@item 0 +30 kHz (default) +@item 1 +125 kHz +@item 2 +250 kHz +@item 3 +1 MHz +@item 4 +2 MHz +@item 5 +2.6 MHz +@item 6 +4 MHz +@item 7 +8 MHz +@end table + +@item @samp{ascii} +Use ASCII mode even when the firmware supports BinMode (binary mode). +BinMode is supported in firmware 2.7 and newer, older FW's either don't +have BinMode or their BinMode is buggy. ASCII mode is slower and makes +the above +@samp{reset=} +and +@samp{speed=} +parameters unavailable. +@end table + +@item Wiring + +When using the Wiring programmer type, the +following optional extended parameter is accepted: +@table @code +@item @samp{snooze=@var{0..32767}} +After performing the port open phase, AVRDUDE will wait/snooze for +@var{snooze} milliseconds before continuing to the protocol sync phase. +No toggling of DTR/RTS is performed if @var{snooze} > 0. +@end table + +@end table + +@page +@c +@c Node +@c +@node Example Command Line Invocations, , Programmers accepting extended parameters, Command Line Options +@section Example Command Line Invocations + +@noindent +Download the file @code{diag.hex} to the ATmega128 chip using the +STK500 programmer connected to the default serial port: + +@smallexample +@cartouche +% avrdude -p m128 -c stk500 -e -U flash:w:diag.hex + +avrdude: AVR device initialized and ready to accept instructions + +Reading | ################################################## | 100% 0.03s + +avrdude: Device signature = 0x1e9702 +avrdude: erasing chip +avrdude: done. +avrdude: performing op: 1, flash, 0, diag.hex +avrdude: reading input file "diag.hex" +avrdude: input file diag.hex auto detected as Intel Hex +avrdude: writing flash (19278 bytes): + +Writing | ################################################## | 100% 7.60s + +avrdude: 19456 bytes of flash written +avrdude: verifying flash memory against diag.hex: +avrdude: load data flash data from input file diag.hex: +avrdude: input file diag.hex auto detected as Intel Hex +avrdude: input file diag.hex contains 19278 bytes +avrdude: reading on-chip flash data: + +Reading | ################################################## | 100% 6.83s + +avrdude: verifying ... +avrdude: 19278 bytes of flash verified + +avrdude: safemode: Fuses OK + +avrdude done. Thank you. + +% +@end cartouche +@end smallexample + +@page +@noindent +Upload the flash memory from the ATmega128 connected to the STK500 +programmer and save it in raw binary format in the file named +@code{c:/diag flash.bin}: + +@smallexample +@cartouche +% avrdude -p m128 -c stk500 -U flash:r:"c:/diag flash.bin":r + +avrdude: AVR device initialized and ready to accept instructions + +Reading | ################################################## | 100% 0.03s + +avrdude: Device signature = 0x1e9702 +avrdude: reading flash memory: + +Reading | ################################################## | 100% 46.10s + +avrdude: writing output file "c:/diag flash.bin" + +avrdude: safemode: Fuses OK + +avrdude done. Thank you. + +% +@end cartouche +@end smallexample + +@page +@noindent +Using the default programmer, download the file @code{diag.hex} to +flash, @code{eeprom.hex} to EEPROM, and set the Extended, High, and Low +fuse bytes to 0xff, 0x89, and 0x2e respectively: + +@smallexample +@cartouche + +% avrdude -p m128 -u -U flash:w:diag.hex \ +> -U eeprom:w:eeprom.hex \ +> -U efuse:w:0xff:m \ +> -U hfuse:w:0x89:m \ +> -U lfuse:w:0x2e:m + +avrdude: AVR device initialized and ready to accept instructions + +Reading | ################################################## | 100% 0.03s + +avrdude: Device signature = 0x1e9702 +avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed + To disable this feature, specify the -D option. +avrdude: erasing chip +avrdude: reading input file "diag.hex" +avrdude: input file diag.hex auto detected as Intel Hex +avrdude: writing flash (19278 bytes): + +Writing | ################################################## | 100% 7.60s + +avrdude: 19456 bytes of flash written +avrdude: verifying flash memory against diag.hex: +avrdude: load data flash data from input file diag.hex: +avrdude: input file diag.hex auto detected as Intel Hex +avrdude: input file diag.hex contains 19278 bytes +avrdude: reading on-chip flash data: + +Reading | ################################################## | 100% 6.84s + +avrdude: verifying ... +avrdude: 19278 bytes of flash verified + +[ ... other memory status output skipped for brevity ... ] + +avrdude done. Thank you. + +% +@end cartouche +@end smallexample + +@page +@noindent +Connect to the JTAG ICE mkII which serial number ends up in 1C37 via +USB, and enter terminal mode: + +@smallexample +@cartouche + +% avrdude -c jtag2 -p m649 -P usb:1c:37 -t + +avrdude: AVR device initialized and ready to accept instructions + +Reading | ################################################## | 100% 0.03s + +avrdude: Device signature = 0x1e9603 + +[ ... terminal mode output skipped for brevity ... ] + +avrdude done. Thank you. + +@end cartouche +@end smallexample + +@noindent +List the serial numbers of all JTAG ICEs attached to USB. This is +done by specifying an invalid serial number, and increasing the +verbosity level. + +@smallexample +@cartouche + +% avrdude -c jtag2 -p m128 -P usb:xx -v +[...] + Using Port : usb:xxx + Using Programmer : jtag2 +avrdude: usbdev_open(): Found JTAG ICE, serno: 00A000001C6B +avrdude: usbdev_open(): Found JTAG ICE, serno: 00A000001C3A +avrdude: usbdev_open(): Found JTAG ICE, serno: 00A000001C30 +avrdude: usbdev_open(): did not find any (matching) USB device "usb:xxx" + +@end cartouche +@end smallexample + + +@c +@c Node +@c +@node Terminal Mode Operation, Configuration File, Command Line Options, Top +@chapter Terminal Mode Operation + +AVRDUDE has an interactive mode called @var{terminal mode} that is +enabled by the @option{-t} option. This mode allows one to enter +interactive commands to display and modify the various device memories, +perform a chip erase, display the device signature bytes and part +parameters, and to send raw programming commands. Commands and +parameters may be abbreviated to their shortest unambiguous form. +Terminal mode also supports a command history so that previously entered +commands can be recalled and edited. + +@menu +* Terminal Mode Commands:: +* Terminal Mode Examples:: +@end menu + +@node Terminal Mode Commands, Terminal Mode Examples, Terminal Mode Operation, Terminal Mode Operation +@section Terminal Mode Commands + +@noindent +The following commands are implemented: + +@table @code + +@item dump @var{memtype} @var{addr} @var{nbytes} +Read @var{nbytes} from the specified memory area, and display them in +the usual hexadecimal and ASCII form. + +@item dump +Continue dumping the memory contents for another @var{nbytes} where the +previous dump command left off. + +@item write @var{memtype} @var{addr} @var{byte1} @dots{} @var{byteN} +Manually program the respective memory cells, starting at address addr, +using the values @var{byte1} through @var{byteN}. This feature is not +implemented for bank-addressed memories such as the flash memory of +ATMega devices. + +@item erase +Perform a chip erase. + +@item send @var{b1} @var{b2} @var{b3} @var{b4} +Send raw instruction codes to the AVR device. If you need access to a +feature of an AVR part that is not directly supported by AVRDUDE, this +command allows you to use it, even though AVRDUDE does not implement the +command. When using direct SPI mode, up to 3 bytes +can be omitted. + +@item sig +Display the device signature bytes. + +@item spi +Enter direct SPI mode. The @emph{pgmled} pin acts as slave select. +@emph{Only supported on parallel bitbang programmers.} + +@item part +Display the current part settings and parameters. Includes chip +specific information including all memory types supported by the +device, read/write timing, etc. + +@item pgm +Return to programming mode (from direct SPI mode). + +@item ? +@itemx help +Give a short on-line summary of the available commands. + +@item quit +Leave terminal mode and thus AVRDUDE. + +@end table + +@noindent +In addition, the following commands are supported on the STK500 +and STK600 programmer: + +@table @code + +@item vtarg @var{voltage} +Set the target's supply voltage to @var{voltage} Volts. + +@item varef [@var{channel}] @var{voltage} +Set the adjustable voltage source to @var{voltage} Volts. +This voltage is normally used to drive the target's +@emph{Aref} input on the STK500 and STK600. +The STK600 offers two reference voltages, which can be +selected by the optional parameter @var{channel} (either +0 or 1). + +@item fosc @var{freq}[@code{M}|@code{k}] +Set the master oscillator to @var{freq} Hz. +An optional trailing letter @code{M} +multiplies by 1E6, a trailing letter @code{k} by 1E3. + +@item fosc off +Turn the master oscillator off. + +@item sck @var{period} +@emph{STK500 and STK600 only:} +Set the SCK clock period to @var{period} microseconds. + +@emph{JTAG ICE only:} +Set the JTAG ICE bit clock period to @var{period} microseconds. +Note that unlike STK500 settings, this setting will be reverted to +its default value (approximately 1 microsecond) when the programming +software signs off from the JTAG ICE. +This parameter can also be used on the JTAG ICE mkII to specify the +ISP clock period when operating the ICE in ISP mode. + +@item parms +@emph{STK500 and STK600 only:} +Display the current voltage and master oscillator parameters. + +@emph{JTAG ICE only:} +Display the current target supply voltage and JTAG bit clock rate/period. + +@end table + +@c +@c Node +@c +@node Terminal Mode Examples, , Terminal Mode Commands, Terminal Mode Operation +@section Terminal Mode Examples + +@noindent +Display part parameters, modify eeprom cells, perform a chip erase: + +@smallexample +@cartouche +% avrdude -p m128 -c stk500 -t + +avrdude: AVR device initialized and ready to accept instructions +avrdude: Device signature = 0x1e9702 +avrdude: current erase-rewrite cycle count is 52 (if being tracked) +avrdude> part +>>> part + +AVR Part : ATMEGA128 +Chip Erase delay : 9000 us +PAGEL : PD7 +BS2 : PA0 +RESET disposition : dedicated +RETRY pulse : SCK +serial program mode : yes +parallel program mode : yes +Memory Detail : + + Page Polled + Memory Type Paged Size Size #Pages MinW MaxW ReadBack + ----------- ------ ------ ---- ------ ----- ----- --------- + eeprom no 4096 8 0 9000 9000 0xff 0xff + flash yes 131072 256 512 4500 9000 0xff 0x00 + lfuse no 1 0 0 0 0 0x00 0x00 + hfuse no 1 0 0 0 0 0x00 0x00 + efuse no 1 0 0 0 0 0x00 0x00 + lock no 1 0 0 0 0 0x00 0x00 + calibration no 1 0 0 0 0 0x00 0x00 + signature no 3 0 0 0 0 0x00 0x00 + +avrdude> dump eeprom 0 16 +>>> dump eeprom 0 16 +0000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + +avrdude> write eeprom 0 1 2 3 4 +>>> write eeprom 0 1 2 3 4 + +avrdude> dump eeprom 0 16 +>>> dump eeprom 0 16 +0000 01 02 03 04 ff ff ff ff ff ff ff ff ff ff ff ff |................| + +avrdude> erase +>>> erase +avrdude: erasing chip +avrdude> dump eeprom 0 16 +>>> dump eeprom 0 16 +0000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + +avrdude> +@end cartouche +@end smallexample + + +@noindent +Program the fuse bits of an ATmega128 (disable M103 compatibility, +enable high speed external crystal, enable brown-out detection, slowly +rising power). Note since we are working with fuse bits the -u (unsafe) +option is specified, which allows you to modify the fuse bits. First +display the factory defaults, then reprogram: + +@smallexample +@cartouche +% avrdude -p m128 -u -c stk500 -t + +avrdude: AVR device initialized and ready to accept instructions +avrdude: Device signature = 0x1e9702 +avrdude: current erase-rewrite cycle count is 52 (if being tracked) +avrdude> d efuse +>>> d efuse +0000 fd |. | + +avrdude> d hfuse +>>> d hfuse +0000 99 |. | + +avrdude> d lfuse +>>> d lfuse +0000 e1 |. | + +avrdude> w efuse 0 0xff +>>> w efuse 0 0xff + +avrdude> w hfuse 0 0x89 +>>> w hfuse 0 0x89 + +avrdude> w lfuse 0 0x2f +>>> w lfuse 0 0x2f + +avrdude> +@end cartouche +@end smallexample + + +@c +@c Node +@c +@node Configuration File, Programmer Specific Information, Terminal Mode Operation, Top +@chapter Configuration File + +@noindent +AVRDUDE reads a configuration file upon startup which describes all of +the parts and programmers that it knows about. The advantage of this is +that if you have a chip that is not currently supported by AVRDUDE, you +can add it to the configuration file without waiting for a new release +of AVRDUDE. Likewise, if you have a parallel port programmer that is +not supported by AVRDUDE, chances are good that you can copy and +existing programmer definition, and with only a few changes, make your +programmer work with AVRDUDE. + +AVRDUDE first looks for a system wide configuration file in a platform +dependent location. On Unix, this is usually +@code{/usr/local/etc/avrdude.conf}, while on Windows it is usally in the +same location as the executable file. The name of this file can be +changed using the @option{-C} command line option. After the system wide +configuration file is parsed, AVRDUDE looks for a per-user configuration +file to augment or override the system wide defaults. On Unix, the +per-user file is @code{.avrduderc} within the user's home directory. On +Windows, this file is the @code{avrdude.rc} file located in the same +directory as the executable. + +@menu +* AVRDUDE Defaults:: +* Programmer Definitions:: +* Part Definitions:: +* Other Notes:: +@end menu + +@c +@c Node +@c +@node AVRDUDE Defaults, Programmer Definitions, Configuration File, Configuration File +@section AVRDUDE Defaults + +@table @code + +@item default_parallel = "@var{default-parallel-device}"; +Assign the default parallel port device. Can be overridden using the +@option{-P} option. + +@item default_serial = "@var{default-serial-device}"; +Assign the default serial port device. Can be overridden using the +@option{-P} option. + +@item default_programmer = "@var{default-programmer-id}"; +Assign the default programmer id. Can be overridden using the @option{-c} +option. + +@item default_bitclock = "@var{default-bitclock}"; +Assign the default bitclock value. Can be overridden using the @option{-B} +option. + +@end table + + +@c +@c Node +@c +@node Programmer Definitions, Part Definitions, AVRDUDE Defaults, Configuration File +@section Programmer Definitions + +@noindent +The format of the programmer definition is as follows: + +@smallexample +programmer + id = [, [, ] ...] ; # are quoted strings + desc = ; # quoted string + type = par | stk500 ; # programmer type + baudrate = ; # baudrate for serial ports + vcc = [, ... ] ; # pin number(s) + reset = ; # pin number + sck = ; # pin number + mosi = ; # pin number + miso = ; # pin number + errled = ; # pin number + rdyled = ; # pin number + pgmled = ; # pin number + vfyled = ; # pin number + ; +@end smallexample + + +@c +@c Node +@c +@node Part Definitions, Other Notes, Programmer Definitions, Configuration File +@section Part Definitions + +@smallexample +part + id = ; # quoted string + desc = ; # quoted string + devicecode = ; # numeric + chip_erase_delay = ; # micro-seconds + pagel = ; # pin name in hex, i.e., 0xD7 + bs2 = ; # pin name in hex, i.e., 0xA0 + reset = dedicated | io; + retry_pulse = reset | sck; + pgm_enable = ; + chip_erase = ; + memory + paged = ; # yes / no + size = ; # bytes + page_size = ; # bytes + num_pages = ; # numeric + min_write_delay = ; # micro-seconds + max_write_delay = ; # micro-seconds + readback_p1 = ; # byte value + readback_p2 = ; # byte value + pwroff_after_write = ; # yes / no + read = ; + write = ; + read_lo = ; + read_hi = ; + write_lo = ; + write_hi = ; + loadpage_lo = ; + loadpage_hi = ; + writepage = ; + ; + ; +@end smallexample + +@menu +* Instruction Format:: +@end menu + +@c +@c Node +@c +@node Instruction Format, , Part Definitions, Part Definitions +@subsection Instruction Format + +@noindent +Instruction formats are specified as a comma separated list of string +values containing information (bit specifiers) about each of the 32 bits +of the instruction. Bit specifiers may be one of the following formats: + +@table @code + +@item 1 +The bit is always set on input as well as output + +@item 0 +the bit is always clear on input as well as output + +@item x +the bit is ignored on input and output + +@item a +the bit is an address bit, the bit-number matches this bit specifier's +position within the current instruction byte + +@item a@var{N} +the bit is the @var{N}th address bit, bit-number = N, i.e., @code{a12} +is address bit 12 on input, @code{a0} is address bit 0. + +@item i +the bit is an input data bit + +@item o +the bit is an output data bit + +@end table + +Each instruction must be composed of 32 bit specifiers. The instruction +specification closely follows the instruction data provided in Atmel's +data sheets for their parts. For example, the EEPROM read and write +instruction for an AT90S2313 AVR part could be encoded as: + +@smallexample + +read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + +write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + +@end smallexample + + + +@c +@c Node +@c +@node Other Notes, , Part Definitions, Configuration File +@section Other Notes + + +@itemize @bullet +@item +The @code{devicecode} parameter is the device code used by the STK500 +and is obtained from the software section (@code{avr061.zip}) of +Atmel's AVR061 application note available from +@url{http://www.atmel.com/atmel/acrobat/doc2525.pdf}. + +@item +Not all memory types will implement all instructions. + +@item +AVR Fuse bits and Lock bits are implemented as a type of memory. + +@item +Example memory types are: @code{flash}, @code{eeprom}, @code{fuse}, +@code{lfuse} (low fuse), @code{hfuse} (high fuse), @code{efuse} +(extended fuse), @code{signature}, @code{calibration}, @code{lock}. + +@item +The memory type specified on the AVRDUDE command line must match one of +the memory types defined for the specified chip. + +@item +The @code{pwroff_after_write} flag causes AVRDUDE to attempt to power +the device off and back on after an unsuccessful write to the affected +memory area if VCC programmer pins are defined. If VCC pins are not +defined for the programmer, a message indicating that the device needs a +power-cycle is printed out. This flag was added to work around a +problem with the at90s4433/2333's; see the at90s4433 errata at: + + @url{http://www.atmel.com/atmel/acrobat/doc1280.pdf} + +@item +The boot loader from application note AVR109 (and thus also the AVR +Butterfly) does not support writing of fuse bits. Writing lock bits +is supported, but is restricted to the boot lock bits (BLBxx). These +are restrictions imposed by the underlying SPM instruction that is used +to program the device from inside the boot loader. Note that programming +the boot lock bits can result in a ``shoot-into-your-foot'' scenario as +the only way to unprogram these bits is a chip erase, which will also +erase the boot loader code. + +The boot loader implements the ``chip erase'' function by erasing the +flash pages of the application section. + +Reading fuse and lock bits is fully supported. + +Note that due to the unability to write the fuse bits, the safemode +functionality does not make sense for these boot loaders. + +@end itemize + +@c +@c Node +@c +@node Programmer Specific Information, Platform Dependent Information, Configuration File, Top +@chapter Programmer Specific Information + +@menu +* Atmel STK600:: +@end menu + +@c +@c Node +@c +@node Atmel STK600, , Programmer Specific Information, Programmer Specific Information +@section Atmel STK600 + +@c +@c Update the table below by running the tools/get-stk600-devices.xsl +@c XSLT transformation on targetboard.xml as shipped by the latest +@c release of AVR Studio. +@c +The following devices are supported by the respective STK600 routing +and socket card: + +@multitable @columnfractions .25 .25 .5 +Routing card @tab Socket card @tab Devices +@item @code{} @tab @code{STK600-ATTINY10} @tab ATtiny4 ATtiny5 ATtiny9 ATtiny10 +@item @code{STK600-RC008T-2} @tab @code{STK600-DIP} @tab ATtiny11 ATtiny12 ATtiny13 ATtiny13A ATtiny25 ATtiny45 ATtiny85 +@item @code{STK600-RC008T-7} @tab @code{STK600-DIP} @tab ATtiny15 +@item @code{STK600-RC014T-42} @tab @code{STK600-SOIC} @tab ATtiny20 +@item @code{STK600-RC020T-1} @tab @code{STK600-DIP} @tab ATtiny2313 ATtiny2313A ATtiny4313 +@item @code{} @tab @code{STK600-TinyX3U} @tab ATtiny43U +@item @code{STK600-RC014T-12} @tab @code{STK600-DIP} @tab ATtiny24 ATtiny44 ATtiny84 ATtiny24A ATtiny44A +@item @code{STK600-RC020T-8} @tab @code{STK600-DIP} @tab ATtiny26 ATtiny261 ATtiny261A ATtiny461 ATtiny861 ATtiny861A +@item @code{STK600-RC020T-43} @tab @code{STK600-SOIC} @tab ATtiny261 ATtiny261A ATtiny461 ATtiny461A ATtiny861 ATtiny861A +@item @code{STK600-RC020T-23} @tab @code{STK600-SOIC} @tab ATtiny87 ATtiny167 +@item @code{STK600-RC028T-3} @tab @code{STK600-DIP} @tab ATtiny28 +@item @code{STK600-RC028M-6} @tab @code{STK600-DIP} @tab ATtiny48 ATtiny88 ATmega8 ATmega8A ATmega48 ATmega88 ATmega168 ATmega48P ATmega48PA ATmega88P ATmega88PA ATmega168P ATmega168PA ATmega328P +@item @code{} @tab @code{QT600-ATTINY88-QT8} @tab ATtiny88 +@item @code{STK600-RC040M-4} @tab @code{STK600-DIP} @tab ATmega8515 ATmega162 +@item @code{STK600-RC044M-30} @tab @code{STK600-TQFP44} @tab ATmega8515 ATmega162 +@item @code{STK600-RC040M-5} @tab @code{STK600-DIP} @tab ATmega8535 ATmega16 ATmega16A ATmega32 ATmega32A ATmega164P ATmega164PA ATmega324P ATmega324PA ATmega644 ATmega644P ATmega644PA ATmega1284P +@item @code{STK600-RC044M-31} @tab @code{STK600-TQFP44} @tab ATmega8535 ATmega16 ATmega16A ATmega32 ATmega32A ATmega164P ATmega164PA ATmega324P ATmega324PA ATmega644 ATmega644P ATmega644PA ATmega1284P +@item @code{} @tab @code{QT600-ATMEGA324-QM64} @tab ATmega324PA +@item @code{STK600-RC032M-29} @tab @code{STK600-TQFP32} @tab ATmega8 ATmega8A ATmega48 ATmega88 ATmega168 ATmega48P ATmega48PA ATmega88P ATmega88PA ATmega168P ATmega168PA ATmega328P +@item @code{STK600-RC064M-9} @tab @code{STK600-TQFP64} @tab ATmega64 ATmega64A ATmega128 ATmega128A ATmega1281 ATmega2561 AT90CAN32 AT90CAN64 AT90CAN128 +@item @code{STK600-RC064M-10} @tab @code{STK600-TQFP64} @tab ATmega165 ATmega165P ATmega169 ATmega169P ATmega169PA ATmega325 ATmega325P ATmega329 ATmega329P ATmega645 ATmega649 ATmega649P +@item @code{STK600-RC100M-11} @tab @code{STK600-TQFP100} @tab ATmega640 ATmega1280 ATmega2560 +@item @code{} @tab @code{STK600-ATMEGA2560} @tab ATmega2560 +@item @code{STK600-RC100M-18} @tab @code{STK600-TQFP100} @tab ATmega3250 ATmega3250P ATmega3290 ATmega3290P ATmega6450 ATmega6490 +@item @code{STK600-RC032U-20} @tab @code{STK600-TQFP32} @tab AT90USB82 AT90USB162 ATmega8U2 ATmega16U2 ATmega32U2 +@item @code{STK600-RC044U-25} @tab @code{STK600-TQFP44} @tab ATmega16U4 ATmega32U4 +@item @code{STK600-RC064U-17} @tab @code{STK600-TQFP64} @tab ATmega32U6 AT90USB646 AT90USB1286 AT90USB647 AT90USB1287 +@item @code{STK600-RCPWM-22} @tab @code{STK600-TQFP32} @tab ATmega32C1 ATmega64C1 ATmega16M1 ATmega32M1 ATmega64M1 +@item @code{STK600-RCPWM-19} @tab @code{STK600-SOIC} @tab AT90PWM2 AT90PWM3 AT90PWM2B AT90PWM3B AT90PWM216 AT90PWM316 +@item @code{STK600-RCPWM-26} @tab @code{STK600-SOIC} @tab AT90PWM81 +@item @code{STK600-RC044M-24} @tab @code{STK600-TSSOP44} @tab ATmega16HVB ATmega32HVB +@item @code{} @tab @code{STK600-HVE2} @tab ATmega64HVE +@item @code{} @tab @code{STK600-ATMEGA128RFA1} @tab ATmega128RFA1 +@item @code{STK600-RC100X-13} @tab @code{STK600-TQFP100} @tab ATxmega64A1 ATxmega128A1 ATxmega128A1_revD ATxmega128A1U +@item @code{} @tab @code{STK600-ATXMEGA1281A1} @tab ATxmega128A1 +@item @code{} @tab @code{QT600-ATXMEGA128A1-QT16} @tab ATxmega128A1 +@item @code{STK600-RC064X-14} @tab @code{STK600-TQFP64} @tab ATxmega64A3 ATxmega128A3 ATxmega256A3 ATxmega64D3 ATxmega128D3 ATxmega192D3 ATxmega256D3 +@item @code{STK600-RC064X-14} @tab @code{STK600-MLF64} @tab ATxmega256A3B +@item @code{STK600-RC044X-15} @tab @code{STK600-TQFP44} @tab ATxmega32A4 ATxmega16A4 ATxmega16D4 ATxmega32D4 +@item @code{} @tab @code{STK600-ATXMEGAT0} @tab ATxmega32T0 +@item @code{} @tab @code{STK600-uC3-144} @tab AT32UC3A0512 AT32UC3A0256 AT32UC3A0128 +@item @code{STK600-RCUC3A144-33} @tab @code{STK600-TQFP144} @tab AT32UC3A0512 AT32UC3A0256 AT32UC3A0128 +@item @code{STK600-RCuC3A100-28} @tab @code{STK600-TQFP100} @tab AT32UC3A1512 AT32UC3A1256 AT32UC3A1128 +@item @code{STK600-RCuC3B0-21} @tab @code{STK600-TQFP64-2} @tab AT32UC3B0256 AT32UC3B0512RevC AT32UC3B0512 AT32UC3B0128 AT32UC3B064 AT32UC3D1128 +@item @code{STK600-RCuC3B48-27} @tab @code{STK600-TQFP48} @tab AT32UC3B1256 AT32UC3B164 +@item @code{STK600-RCUC3A144-32} @tab @code{STK600-TQFP144} @tab AT32UC3A3512 AT32UC3A3256 AT32UC3A3128 AT32UC3A364 AT32UC3A3256S AT32UC3A3128S AT32UC3A364S +@item @code{STK600-RCUC3C0-36} @tab @code{STK600-TQFP144} @tab AT32UC3C0512 AT32UC3C0256 AT32UC3C0128 AT32UC3C064 +@item @code{STK600-RCUC3C1-38} @tab @code{STK600-TQFP100} @tab AT32UC3C1512 AT32UC3C1256 AT32UC3C1128 AT32UC3C164 +@item @code{STK600-RCUC3C2-40} @tab @code{STK600-TQFP64-2} @tab AT32UC3C2512 AT32UC3C2256 AT32UC3C2128 AT32UC3C264 +@item @code{STK600-RCUC3C0-37} @tab @code{STK600-TQFP144} @tab AT32UC3C0512 AT32UC3C0256 AT32UC3C0128 AT32UC3C064 +@item @code{STK600-RCUC3C1-39} @tab @code{STK600-TQFP100} @tab AT32UC3C1512 AT32UC3C1256 AT32UC3C1128 AT32UC3C164 +@item @code{STK600-RCUC3C2-41} @tab @code{STK600-TQFP64-2} @tab AT32UC3C2512 AT32UC3C2256 AT32UC3C2128 AT32UC3C264 +@item @code{STK600-RCUC3L0-34} @tab @code{STK600-TQFP48} @tab AT32UC3L064 AT32UC3L032 AT32UC3L016 +@item @code{} @tab @code{QT600-AT32UC3L-QM64} @tab AT32UC3L064 +@end multitable + +Ensure the correct socket and routing card are mounted @emph{before} +powering on the STK600. While the STK600 firmware ensures the socket +and routing card mounted match each other (using a table stored +internally in nonvolatile memory), it cannot handle the case where a +wrong routing card is used, e. g. the routing card +@code{STK600-RC040M-5} (which is meant for 40-pin DIP AVRs that have +an ADC, with the power supply pins in the center of the package) was +used but an ATmega8515 inserted (which uses the ``industry standard'' +pinout with Vcc and GND at opposite corners). + +Note that for devices that use the routing card @code{STK600-RC008T-2}, +in order to use ISP mode, the jumper for @code{AREF0} must be removed +as it would otherwise block one of the ISP signals. High-voltage +serial programming can be used even with that jumper installed. + +The ISP system of the STK600 contains a detection against shortcuts +and other wiring errors. AVRDUDE initiates a connection check before +trying to enter ISP programming mode, and display the result if the +target is not found ready to be ISP programmed. + +High-voltage programming requires the target voltage to be set to at +least 4.5 V in order to work. This can be done using +@emph{Terminal Mode}, see @ref{Terminal Mode Operation}. + +@c +@c Node +@c +@node Platform Dependent Information, Troubleshooting, Programmer Specific Information, Top +@appendix Platform Dependent Information + +@menu +* Unix:: +* Windows:: +@end menu + +@c +@c Node +@c +@node Unix, Windows, Platform Dependent Information, Platform Dependent Information +@section Unix + +@menu +* Unix Installation:: +* Unix Configuration Files:: +* Unix Port Names:: +* Unix Documentation:: +@end menu + +@c +@c Node +@c +@node Unix Installation, Unix Configuration Files, Unix, Unix +@subsection Unix Installation + +@noindent +To build and install from the source tarball on Unix like systems: + +@example +$ gunzip -c avrdude-@value{VERSION}.tar.gz | tar xf - +$ cd avrdude-@value{VERSION} +$ ./configure +$ make +$ su root -c 'make install' +@end example + +The default location of the install is into @code{/usr/local} so you +will need to be sure that @code{/usr/local/bin} is in your @code{PATH} +environment variable. + +If you do not have root access to your system, you can do the the +following instead: + +@example +$ gunzip -c avrdude-@value{VERSION}.tar.gz | tar xf - +$ cd avrdude-@value{VERSION} +$ ./configure --prefix=$HOME/local +$ make +$ make install +@end example + +@menu +* FreeBSD Installation:: +* Linux Installation:: +@end menu + +@c +@c Node +@c +@node FreeBSD Installation, Linux Installation, Unix Installation, Unix Installation +@subsubsection FreeBSD Installation + +@noindent +AVRDUDE is installed via the FreeBSD Ports Tree as follows: + +@example +% su - root +# cd /usr/ports/devel/avrdude +# make install +@end example + +If you wish to install from a pre-built package instead of the source, +you can use the following instead: + +@example +% su - root +# pkg_add -r avrdude +@end example + +Of course, you must be connected to the Internet for these methods to +work, since that is where the source as well as the pre-built package is +obtained. + +@c +@c Node +@c +@node Linux Installation, , FreeBSD Installation, Unix Installation +@subsubsection Linux Installation + +@noindent +On rpm based Linux systems (such as RedHat, SUSE, Mandrake, etc), you +can build and install the rpm binaries directly from the tarball: + +@example +$ su - root +# rpmbuild -tb avrdude-@value{VERSION}.tar.gz +# rpm -Uvh /usr/src/redhat/RPMS/i386/avrdude-@value{VERSION}-1.i386.rpm +@end example + +Note that the path to the resulting rpm package, differs from system +to system. The above example is specific to RedHat. + +@c +@c Node +@c +@node Unix Configuration Files, Unix Port Names, Unix Installation, Unix +@subsection Unix Configuration Files + +@noindent +When AVRDUDE is build using the default @option{--prefix} configure +option, the default configuration file for a Unix system is located at +@code{/usr/local/etc/avrdude.conf}. This can be overridden by using the +@option{-C} command line option. Additionally, the user's home directory +is searched for a file named @code{.avrduderc}, and if found, is used to +augment the system default configuration file. + +@menu +* FreeBSD Configuration Files:: +* Linux Configuration Files:: +@end menu + +@c +@c Node +@c +@node FreeBSD Configuration Files, Linux Configuration Files, Unix Configuration Files, Unix Configuration Files +@subsubsection FreeBSD Configuration Files + +@noindent +When AVRDUDE is installed using the FreeBSD ports system, the system +configuration file is always @code{/usr/local/etc/avrdude.conf}. + +@c +@c Node +@c +@node Linux Configuration Files, , FreeBSD Configuration Files, Unix Configuration Files +@subsubsection Linux Configuration Files + +@noindent +When AVRDUDE is installed using from an rpm package, the system +configuration file will be always be @code{/etc/avrdude.conf}. + +@c +@c Node +@c +@node Unix Port Names, Unix Documentation, Unix Configuration Files, Unix +@subsection Unix Port Names + +@noindent +The parallel and serial port device file names are system specific. +The following table lists the default names for a given system. + +@multitable @columnfractions .30 .30 .30 +@item @strong{System} + @tab @strong{Default Parallel Port} + @tab @strong{Default Serial Port} +@item FreeBSD + @tab @code{/dev/ppi0} + @tab @code{/dev/cuad0} +@item Linux + @tab @code{/dev/parport0} + @tab @code{/dev/ttyS0} +@item Solaris + @tab @code{/dev/printers/0} + @tab @code{/dev/term/a} +@end multitable + +On FreeBSD systems, AVRDUDE uses the ppi(4) interface for +accessing the parallel port and the sio(4) driver for serial port +access. + +On Linux systems, AVRDUDE uses the ppdev interface for +accessing the parallel port and the tty driver for serial port +access. + +On Solaris systems, AVRDUDE uses the ecpp(7D) driver for +accessing the parallel port and the asy(7D) driver for serial port +access. + +@c +@c Node +@c +@node Unix Documentation, , Unix Port Names, Unix +@subsection Unix Documentation + +@noindent +AVRDUDE installs a manual page as well as info, HTML and PDF +documentation. The manual page is installed in +@code{/usr/local/man/man1} area, while the HTML and PDF documentation +is installed in @code{/usr/local/share/doc/avrdude} directory. The +info manual is installed in @code{/usr/local/info/avrdude.info}. + +Note that these locations can be altered by various configure options +such as @option{--prefix}. + +@c +@c Node +@c +@node Windows, , Unix, Platform Dependent Information +@section Windows + +@menu +* Windows Installation:: +* Windows Configuration Files:: +* Windows Port Names:: +* Using the parallel port:: +* Documentation:: +* Credits.:: +@end menu + +@c +@c Node +@c +@node Windows Installation, Windows Configuration Files, Windows, Windows +@subsection Installation + +@noindent +A Windows executable of avrdude is included in WinAVR which can be found at +@url{http://sourceforge.net/projects/winavr}. WinAVR is a suite of executable, +open source software development tools for the AVR for the Windows platform. + +There are two options to build avrdude from source under Windows. +The first one is to use Cygwin (@url{http://www.cygwin.com/}). + +To build and install from the source tarball for Windows (using Cygwin): + +@example +$ set PREFIX= +$ export PREFIX +$ gunzip -c avrdude-@value{VERSION}.tar.gz | tar xf - +$ cd avrdude-@value{VERSION} +$ ./configure LDFLAGS="-static" --prefix=$PREFIX --datadir=$PREFIX +--sysconfdir=$PREFIX/bin --enable-versioned-doc=no +$ make +$ make install +@end example + +Note that recent versions of Cygwin (starting with 1.7) removed the +MinGW support from the compiler that is needed in order to build a +native Win32 API binary that does not require to install the Cygwin +library @code{cygwin1.dll} at run-time. Either try using an older +compiler version that still supports MinGW builds, or use MinGW +(@url{http://www.mingw.org/}) directly. + +@c +@c XXX Please add more detailed instructions here. +@c + + +@c +@c Node +@c +@node Windows Configuration Files, Windows Port Names, Windows Installation, Windows +@subsection Configuration Files + +@menu +* Configuration file names:: +* How AVRDUDE finds the configuration files.:: +@end menu + +@c +@c Node +@c +@node Configuration file names, How AVRDUDE finds the configuration files., Windows Configuration Files, Windows Configuration Files +@subsubsection Configuration file names + +@noindent +AVRDUDE on Windows looks for a system configuration file name of +@code{avrdude.conf} and looks for a user override configuration file of +@code{avrdude.rc}. + +@c +@c Node +@c +@node How AVRDUDE finds the configuration files., , Configuration file names, Windows Configuration Files +@subsubsection How AVRDUDE finds the configuration files. + +@noindent +AVRDUDE on Windows has a different way of searching for the system and +user configuration files. Below is the search method for locating the +configuration files: + +@enumerate + +@item +The directory from which the application loaded. + +@item +The current directory. + +@item +The Windows system directory. On Windows NT, the name of this directory +is @code{SYSTEM32}. + +@item +Windows NT: The 16-bit Windows system directory. The name of this +directory is @code{SYSTEM}. + +@item +The Windows directory. + +@item +The directories that are listed in the PATH environment variable. + +@end enumerate + + +@c +@c Node +@c +@node Windows Port Names, Using the parallel port, Windows Configuration Files, Windows +@subsection Port Names + +@menu +* Serial Ports:: +* Parallel Ports:: +@end menu + +@c +@c Node +@c +@node Serial Ports, Parallel Ports, Windows Port Names, Windows Port Names +@subsubsection Serial Ports + +@noindent +When you select a serial port (i.e. when using an STK500) use the +Windows serial port device names such as: com1, com2, etc. + +@c +@c Node +@c +@node Parallel Ports, , Serial Ports, Windows Port Names +@subsubsection Parallel Ports + +@noindent +AVRDUDE will accept 3 Windows parallel port names: lpt1, lpt2, or +lpt3. Each of these names corresponds to a fixed parallel port base +address: + +@table @code +@item lpt1 +0x378 + +@item lpt2 +0x278 + +@item lpt3 +0x3BC + +@end table + +On your desktop PC, lpt1 will be the most common choice. If you are +using a laptop, you might have to use lpt3 instead of lpt1. Select the +name of the port the corresponds to the base address of the parallel +port that you want. + +If the parallel port can be accessed through a different +address, this address can be specified directly, using the common C +language notation (i. e., hexadecimal values are prefixed by @code{0x}). + +@c +@c Node +@c +@node Using the parallel port, Documentation, Windows Port Names, Windows +@subsection Using the parallel port + +@menu +* Windows NT/2K/XP:: +* Windows 95/98:: +@end menu + +@c +@c Node +@c +@node Windows NT/2K/XP, Windows 95/98, Using the parallel port, Using the parallel port +@subsubsection Windows NT/2K/XP + +@noindent +On Windows NT, 2000, and XP user applications cannot directly access the +parallel port. However, kernel mode drivers can access the parallel port. +giveio.sys is a driver that can allow user applications to set the state +of the parallel port pins. + +Before using AVRDUDE, the giveio.sys driver must be loaded. The +accompanying command-line program, loaddrv.exe, can do just that. + +To make things even easier there are 3 batch files that are also +included: + +@enumerate +@item install_giveio.bat +Install and start the giveio driver. + +@item status_giveio.bat +Check on the status of the giveio driver. + +@item remove_giveio.bat +Stop and remove the giveio driver from memory. +@end enumerate + +These 3 batch files calls the loaddrv program with various options to +install, start, stop, and remove the driver. + +When you first execute install_giveio.bat, loaddrv.exe and giveio.sys +must be in the current directory. When install_giveio.bat is executed it +will copy giveio.sys from your current directory to your Windows +directory. It will then load the driver from the Windows directory. This +means that after the first time install_giveio is executed, you should +be able to subsequently execute the batch file from any directory and have +it successfully start the driver. + +Note that you must have administrator privilege to load the giveio driver. + +@c +@c Node +@c +@node Windows 95/98, , Windows NT/2K/XP, Using the parallel port +@subsubsection Windows 95/98 + +@noindent +On Windows 95 and 98 the giveio.sys driver is not needed. + + +@c +@c Node +@c +@node Documentation, Credits., Using the parallel port, Windows +@subsection Documentation + +@noindent +AVRDUDE installs a manual page as well as info, HTML and PDF +documentation. The manual page is installed in +@code{/usr/local/man/man1} area, while the HTML and PDF documentation +is installed in @code{/usr/local/share/doc/avrdude} directory. The +info manual is installed in @code{/usr/local/info/avrdude.info}. + +Note that these locations can be altered by various configure options +such as @option{--prefix} and @option{--datadir}. + + +@c +@c Node +@c +@node Credits., , Documentation, Windows +@subsection Credits. + +@noindent +Thanks to: + +@itemize @bullet +@item +Dale Roberts for the giveio driver. + +@item +Paula Tomlinson for the loaddrv sources. + +@item +Chris Liechti for modifying loaddrv to be command +line driven and for writing the batch files. + +@end itemize + +@c +@c Node +@c +@node Troubleshooting, ,Platform Dependent Information ,Top +@appendix Troubleshooting + +@noindent +In general, please report any bugs encountered via +@* +@url{http://savannah.nongnu.org/bugs/?group=avrdude}. + + +@itemize @bullet + +@item +Problem: I'm using a serial programmer under Windows and get the following +error: + +@code{avrdude: serial_open(): can't set attributes for device "com1"}, + +Solution: This problem seems to appear with certain versions of Cygwin. Specifying +@code{"/dev/com1"} instead of @code{"com1"} should help. + + +@item +Problem: I'm using Linux and my AVR910 programmer is really slow. + +Solution (short): @code{setserial @var{port} low_latency} + +Solution (long): +There are two problems here. First, the system may wait some time before it +passes data from the serial port to the program. Under Linux the following +command works around this (you may need root privileges for this). + +@code{setserial @var{port} low_latency} + +Secondly, the serial interface chip may delay the interrupt for some time. +This behaviour can be changed by setting the FIFO-threshold to one. Under Linux this +can only be done by changing the kernel source in @code{drivers/char/serial.c}. +Search the file for @code{UART_FCR_TRIGGER_8} and replace it with @code{UART_FCR_TRIGGER_1}. Note that overall performance might suffer if there +is high throughput on serial lines. Also note that you are modifying the kernel at +your own risk. + + +@item +Problem: I'm not using Linux and my AVR910 programmer is really slow. + +Solutions: The reasons for this are the same as above. +If you know how to work around this on your OS, please let us know. + +@item +Problem: Updating the flash ROM from terminal mode does not work with the +JTAG ICEs. + +Solution: None at this time. Currently, the JTAG ICE code cannot +write to the flash ROM one byte at a time. + +@item +Problem: Page-mode programming the EEPROM (using the -U option) does +not erase EEPROM cells before writing, and thus cannot overwrite any +previous value != 0xff. + +Solution: None. This is an inherent feature of the way JTAG EEPROM +programming works, and is documented that way in the Atmel AVR +datasheets. +In order to successfully program the EEPROM that way, a prior chip +erase (with the EESAVE fuse unprogrammed) is required. +This also applies to the STK500 and STK600 in high-voltage programming mode. + +@item +Problem: How do I turn off the @var{DWEN} fuse? + +Solution: If the @var{DWEN} (debugWire enable) fuse is activated, +the @var{/RESET} pin is not functional anymore, so normal ISP +communication cannot be established. +There are two options to deactivate that fuse again: high-voltage +programming, or getting the JTAG ICE mkII talk debugWire, and +prepare the target AVR to accept normal ISP communication again. + +The first option requires a programmer that is capable of high-voltage +programming (either serial or parallel, depending on the AVR device), +for example the STK500. In high-voltage programming mode, the +@var{/RESET} pin is activated initially using a 12 V pulse (thus the +name @emph{high voltage}), so the target AVR can subsequently be +reprogrammed, and the @var{DWEN} fuse can be cleared. Typically, this +operation cannot be performed while the AVR is located in the target +circuit though. + +The second option requires a JTAG ICE mkII that can talk the debugWire +protocol. The ICE needs to be connected to the target using the +JTAG-to-ISP adapter, so the JTAG ICE mkII can be used as a debugWire +initiator as well as an ISP programmer. AVRDUDE will then be activated +using the @var{jtag2isp} programmer type. The initial ISP +communication attempt will fail, but AVRDUDE then tries to initiate a +debugWire reset. When successful, this will leave the target AVR in a +state where it can accept standard ISP communication. The ICE is then +signed off (which will make it signing off from the USB as well), so +AVRDUDE has to be called again afterwards. This time, standard ISP +communication can work, so the @var{DWEN} fuse can be cleared. + +The pin mapping for the JTAG-to-ISP adapter is: + +@multitable @columnfractions .2 .2 +@item @strong{JTAG pin} @tab @strong{ISP pin} +@item 1 @tab 3 +@item 2 @tab 6 +@item 3 @tab 1 +@item 4 @tab 2 +@item 6 @tab 5 +@item 9 @tab 4 +@end multitable + +@item +Problem: Multiple USBasp or USBtinyISP programmers connected simultaneously are not +found. + +Solution: The USBtinyISP code supports distinguishing multiple +programmers based on their bus:device connection tuple that describes +their place in the USB hierarchy on a specific host. This tuple can +be added to the @var{-P usb} option, similar to adding a serial number +on other USB-based programmers. + +The actual naming convention for the bus and device names is +operating-system dependant; AVRDUDE will print out what it found +on the bus when running it with (at least) one @var{-v} option. +By specifying a string that cannot match any existing device +(for example, @var{-P usb:xxx}), the scan will list all possible +candidate devices found on the bus. + +Examples: +@example +avrdude -c usbtiny -p atmega8 -P usb:003:025 (Linux) +avrdude -c usbtiny -p atmega8 -P usb:/dev/usb:/dev/ugen1.3 (FreeBSD 8+) +avrdude -c usbtiny -p atmega8 \ + -P usb:bus-0:\\.\libusb0-0001--0x1781-0x0c9f (Windows) +@end example + +@item +Problem: I cannot do @dots{} when the target is in debugWire mode. + +Solution: debugWire mode imposes several limitations. + +The debugWire protocol is Atmel's proprietary one-wire (plus ground) +protocol to allow an in-circuit emulation of the smaller AVR devices, +using the @var{/RESET} line. +DebugWire mode is initiated by activating the @var{DWEN} +fuse, and then power-cycling the target. +While this mode is mainly intended for debugging/emulation, it +also offers limited programming capabilities. +Effectively, the only memory areas that can be read or programmed +in this mode are flash ROM and EEPROM. +It is also possible to read out the signature. +All other memory areas cannot be accessed. +There is no +@emph{chip erase} +functionality in debugWire mode; instead, while reprogramming the +flash ROM, each flash ROM page is erased right before updating it. +This is done transparently by the JTAG ICE mkII (or AVR Dragon). +The only way back from debugWire mode is to initiate a special +sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the +debugWire mode will be temporarily disabled, and the target can +be accessed using normal ISP programming. +This sequence is automatically initiated by using the JTAG ICE mkII +or AVR Dragon in ISP mode, when they detect that ISP mode cannot be +entered. + +@item +Problem: I want to use my JTAG ICE mkII to program an +Xmega device through PDI. The documentation tells me to use the +@emph{XMEGA PDI adapter for JTAGICE mkII} that is supposed to ship +with the kit, yet I don't have it. + +Solution: Use the following pin mapping: + +@multitable @columnfractions .2 .2 .2 .2 +@item @strong{JTAGICE} @tab @strong{Target} @tab @strong{Squid cab-} @tab @strong{PDI} +@item @strong{mkII probe} @tab @strong{pins} @tab @strong{le colors} @tab @strong{header} +@item 1 (TCK) @tab @tab Black @tab +@item 2 (GND) @tab GND @tab White @tab 6 +@item 3 (TDO) @tab @tab Grey @tab +@item 4 (VTref) @tab VTref @tab Purple @tab 2 +@item 5 (TMS) @tab @tab Blue @tab +@item 6 (nSRST) @tab PDI_CLK @tab Green @tab 5 +@item 7 (N.C.) @tab @tab Yellow @tab +@item 8 (nTRST) @tab @tab Orange @tab +@item 9 (TDI) @tab PDI_DATA @tab Red @tab 1 +@item 10 (GND) @tab @tab Brown @tab +@end multitable + +@item +Problem: I want to use my AVR Dragon to program an +Xmega device through PDI. + +Solution: Use the 6 pin ISP header on the Dragon and the following pin mapping: + +@multitable @columnfractions .2 .2 +@item @strong{Dragon} @tab @strong{Target} +@item @strong{ISP Header} @tab @strong{pins} +@item 1 (MISO) @tab PDI_DATA +@item 2 (VCC) @tab VCC +@item 3 (SCK) @tab +@item 4 (MOSI) @tab +@item 5 (RESET) @tab PDI_CLK / RST +@item 6 (GND) @tab GND +@end multitable + +@item +Problem: I want to use my AVRISP mkII to program an +ATtiny4/5/9/10 device through TPI. How to connect the pins? + +Solution: Use the following pin mapping: + +@multitable @columnfractions .2 .2 .2 +@item @strong{AVRISP} @tab @strong{Target} @tab @strong{ATtiny} +@item @strong{connector} @tab @strong{pins} @tab @strong{pin #} +@item 1 (MISO) @tab TPIDATA @tab 1 +@item 2 (VTref) @tab Vcc @tab 5 +@item 3 (SCK) @tab TPICLK @tab 3 +@item 4 (MOSI) @tab @tab +@item 5 (RESET) @tab /RESET @tab 6 +@item 6 (GND) @tab GND @tab 2 +@end multitable + +@item +Problem: I want to program an ATtiny4/5/9/10 device using a serial/parallel +bitbang programmer. How to connect the pins? + +Solution: Since TPI has only 1 pin for bi-directional data transfer, both +@var{MISO} and @var{MOSI} pins should be connected to the @var{TPIDATA} pin +on the ATtiny device. +However, a 1K resistor should be placed between the @var{MOSI} and @var{TPIDATA}. +The @var{MISO} pin connects to @var{TPIDATA} directly. +The @var{SCK} pin is connected to @var{TPICLK}. + +In addition, the @var{Vcc}, @var{/RESET} and @var{GND} pins should +be connected to their respective ports on the ATtiny device. + +@item +Problem: How can I use a FTDI FT232R USB-to-Serial device for bitbang programming? + +Solution: When connecting the FT232 directly to the pins of the target Atmel device, +the polarity of the pins defined in the @code{programmer} definition should be +inverted by prefixing a tilde. For example, the @var{dasa} programmer would +look like this when connected via a FT232R device (notice the tildes in +front of pins 7, 4, 3 and 8): + +@example +programmer + id = "dasa_ftdi"; + desc = "serial port banging, reset=rts sck=dtr mosi=txd miso=cts"; + type = serbb; + reset = ~7; + sck = ~4; + mosi = ~3; + miso = ~8; +; +@end example + +Note that this uses the FT232 device as a normal serial port, not using the +FTDI drivers in the special bitbang mode. + +@item +Problem: My ATtiny4/5/9/10 reads out fine, but any attempt to program +it (through TPI) fails. Instead, the memory retains the old contents. + +Solution: Mind the limited programming supply voltage range of these +devices. + +In-circuit programming through TPI is only guaranteed by the datasheet +at Vcc = 5 V. + +@item +Problem: My ATxmega@dots{}A1/A2/A3 cannot be programmed through PDI with +my AVR Dragon. Programming through a JTAG ICE mkII works though, as does +programming through JTAG. + +Solution: None by this time (2010 Q1). + +It is said that the AVR Dragon can only program devices from the A4 +Xmega sub-family. + +@item +Problem: when programming with an AVRISPmkII or STK600, AVRDUDE hangs +when programming files of a certain size (e.g. 246 bytes). Other +(larger or smaller) sizes work though. + +Solution: This is a bug caused by an incorrect handling of zero-length +packets (ZLPs) in some versions of the libusb 0.1 API wrapper that ships +with libusb 1.x in certain Linux distributions. All Linux systems with +kernel versions < 2.6.31 and libusb >= 1.0.0 < 1.0.3 are reported to be +affected by this. + +See also: @url{http://www.libusb.org/ticket/6} + +@end itemize + + + +@bye + diff --git a/avrdude/fileio.c b/avrdude/fileio.c new file mode 100644 index 00000000..5af91bab --- /dev/null +++ b/avrdude/fileio.c @@ -0,0 +1,1159 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "fileio.h" + + +#define IHEX_MAXDATA 256 + +#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */ + + +struct ihexrec { + unsigned char reclen; + unsigned int loadofs; + unsigned char rectyp; + unsigned char data[IHEX_MAXDATA]; + unsigned char cksum; +}; + + +static int b2ihex(unsigned char * inbuf, int bufsize, + int recsize, int startaddr, + char * outfile, FILE * outf); + +static int ihex2b(char * infile, FILE * inf, + unsigned char * outbuf, int bufsize); + +static int b2srec(unsigned char * inbuf, int bufsize, + int recsize, int startaddr, + char * outfile, FILE * outf); + +static int srec2b(char * infile, FILE * inf, + unsigned char * outbuf, int bufsize); + +static int ihex_readrec(struct ihexrec * ihex, char * rec); + +static int srec_readrec(struct ihexrec * srec, char * rec); + +static int fileio_rbin(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size); + +static int fileio_ihex(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size); + +static int fileio_srec(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size); + +static int fileio_num(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size, + FILEFMT fmt); + +static int fmt_autodetect(char * fname); + + + +char * fmtstr(FILEFMT format) +{ + switch (format) { + case FMT_AUTO : return "auto-detect"; break; + case FMT_SREC : return "Motorola S-Record"; break; + case FMT_IHEX : return "Intel Hex"; break; + case FMT_RBIN : return "raw binary"; break; + default : return "invalid format"; break; + }; +} + + + +static int b2ihex(unsigned char * inbuf, int bufsize, + int recsize, int startaddr, + char * outfile, FILE * outf) +{ + unsigned char * buf; + unsigned int nextaddr; + int n, nbytes, n_64k; + int i; + unsigned char cksum; + + if (recsize > 255) { + fprintf(stderr, "%s: recsize=%d, must be < 256\n", + progname, recsize); + return -1; + } + + n_64k = 0; + nextaddr = startaddr; + buf = inbuf; + nbytes = 0; + + while (bufsize) { + n = recsize; + if (n > bufsize) + n = bufsize; + + if ((nextaddr + n) > 0x10000) + n = 0x10000 - nextaddr; + + if (n) { + cksum = 0; + fprintf(outf, ":%02X%04X00", n, nextaddr); + cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff); + for (i=0; i= 0x10000) { + int lo, hi; + /* output an extended address record */ + n_64k++; + lo = n_64k & 0xff; + hi = (n_64k >> 8) & 0xff; + cksum = 0; + fprintf(outf, ":02000004%02X%02X", hi, lo); + cksum += 2 + 0 + 4 + hi + lo; + cksum = -cksum; + fprintf(outf, "%02X\n", cksum); + nextaddr = 0; + } + + /* advance to next 'recsize' bytes */ + buf += n; + bufsize -= n; + } + + /*----------------------------------------------------------------- + add the end of record data line + -----------------------------------------------------------------*/ + cksum = 0; + n = 0; + nextaddr = 0; + fprintf(outf, ":%02X%04X01", n, nextaddr); + cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff) + 1; + cksum = -cksum; + fprintf(outf, "%02X\n", cksum); + + return nbytes; +} + + +static int ihex_readrec(struct ihexrec * ihex, char * rec) +{ + int i, j; + char buf[8]; + int offset, len; + char * e; + unsigned char cksum; + int rc; + + len = strlen(rec); + offset = 1; + cksum = 0; + + /* reclen */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->reclen = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + /* load offset */ + if (offset + 4 > len) + return -1; + for (i=0; i<4; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->loadofs = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + /* record type */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->rectyp = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + cksum = ihex->reclen + ((ihex->loadofs >> 8) & 0x0ff) + + (ihex->loadofs & 0x0ff) + ihex->rectyp; + + /* data */ + for (j=0; jreclen; j++) { + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->data[j] = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + cksum += ihex->data[j]; + } + + /* cksum */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->cksum = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + rc = -cksum & 0x000000ff; + + return rc; +} + + + +/* + * Intel Hex to binary buffer + * + * Given an open file 'inf' which contains Intel Hex formated data, + * parse the file and lay it out within the memory buffer pointed to + * by outbuf. The size of outbuf, 'bufsize' is honored; if data would + * fall outsize of the memory buffer outbuf, an error is generated. + * + * Return the maximum memory address within 'outbuf' that was written. + * If an error occurs, return -1. + * + * */ +static int ihex2b(char * infile, FILE * inf, + unsigned char * outbuf, int bufsize) +{ + char buffer [ MAX_LINE_LEN ]; + unsigned char * buf; + unsigned int nextaddr, baseaddr, maxaddr, offsetaddr; + int i; + int lineno; + int len; + struct ihexrec ihex; + int rc; + + lineno = 0; + buf = outbuf; + baseaddr = 0; + maxaddr = 0; + offsetaddr = 0; + nextaddr = 0; + + while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { + lineno++; + len = strlen(buffer); + if (buffer[len-1] == '\n') + buffer[--len] = 0; + if (buffer[0] != ':') + continue; + rc = ihex_readrec(&ihex, buffer); + if (rc < 0) { + fprintf(stderr, "%s: invalid record at line %d of \"%s\"\n", + progname, lineno, infile); + return -1; + } + else if (rc != ihex.cksum) { + fprintf(stderr, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n", + progname, lineno, infile); + fprintf(stderr, "%s: checksum=0x%02x, computed checksum=0x%02x\n", + progname, ihex.cksum, rc); + return -1; + } + + switch (ihex.rectyp) { + case 0: /* data record */ + nextaddr = ihex.loadofs + baseaddr; + if ((nextaddr + ihex.reclen) > (bufsize+offsetaddr)) { + fprintf(stderr, + "%s: ERROR: address 0x%04x out of range at line %d of %s\n", + progname, nextaddr+ihex.reclen, lineno, infile); + return -1; + } + for (i=0; i maxaddr) + maxaddr = nextaddr+ihex.reclen; + break; + + case 1: /* end of file record */ + return maxaddr-offsetaddr; + break; + + case 2: /* extended segment address record */ + baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 4; + break; + + case 3: /* start segment address record */ + /* we don't do anything with the start address */ + break; + + case 4: /* extended linear address record */ + baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 16; + if(nextaddr == 0) offsetaddr = baseaddr; // if provided before any data, then remember it + break; + + case 5: /* start linear address record */ + /* we don't do anything with the start address */ + break; + + default: + fprintf(stderr, + "%s: don't know how to deal with rectype=%d " + "at line %d of %s\n", + progname, ihex.rectyp, lineno, infile); + return -1; + break; + } + + } /* while */ + + fprintf(stderr, + "%s: WARNING: no end of file record found for Intel Hex " + "file \"%s\"\n", + progname, infile); + + return maxaddr-offsetaddr; +} + +static int b2srec(unsigned char * inbuf, int bufsize, + int recsize, int startaddr, + char * outfile, FILE * outf) +{ + unsigned char * buf; + unsigned int nextaddr; + int n, nbytes, addr_width; + int i; + unsigned char cksum; + + char * tmpl=0; + + if (recsize > 255) { + fprintf(stderr, "%s: ERROR: recsize=%d, must be < 256\n", + progname, recsize); + return -1; + } + + nextaddr = startaddr; + buf = inbuf; + nbytes = 0; + + addr_width = 0; + + while (bufsize) { + + n = recsize; + + if (n > bufsize) + n = bufsize; + + if (n) { + cksum = 0; + if (nextaddr + n <= 0xffff) { + addr_width = 2; + tmpl="S1%02X%04X"; + } + else if (nextaddr + n <= 0xffffff) { + addr_width = 3; + tmpl="S2%02X%06X"; + } + else if (nextaddr + n <= 0xffffffff) { + addr_width = 4; + tmpl="S3%02X%08X"; + } + else { + fprintf(stderr, "%s: ERROR: address=%d, out of range\n", + progname, nextaddr); + return -1; + } + + fprintf(outf, tmpl, n + addr_width + 1, nextaddr); + + cksum += n + addr_width + 1; + + for (i=addr_width; i>0; i--) + cksum += (nextaddr >> (i-1) * 8) & 0xff; + + for (i=nextaddr; i0; i--) + cksum += (nextaddr >> (i - 1) * 8) & 0xff; + cksum = 0xff - cksum; + fprintf(outf, "%02X\n", cksum); + + return nbytes; +} + + +static int srec_readrec(struct ihexrec * srec, char * rec) +{ + int i, j; + char buf[8]; + int offset, len, addr_width; + char * e; + unsigned char cksum; + int rc; + + len = strlen(rec); + offset = 1; + cksum = 0; + addr_width = 2; + + /* record type */ + if (offset + 1 > len) + return -1; + srec->rectyp = rec[offset++]; + if (srec->rectyp == 0x32 || srec->rectyp == 0x38) + addr_width = 3; /* S2,S8-record */ + else if (srec->rectyp == 0x33 || srec->rectyp == 0x37) + addr_width = 4; /* S3,S7-record */ + + /* reclen */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + srec->reclen = strtoul(buf, &e, 16); + cksum += srec->reclen; + srec->reclen -= (addr_width+1); + if (e == buf || *e != 0) + return -1; + + /* load offset */ + if (offset + addr_width > len) + return -1; + for (i=0; iloadofs = strtoull(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + for (i=addr_width; i>0; i--) + cksum += (srec->loadofs >> (i - 1) * 8) & 0xff; + + /* data */ + for (j=0; jreclen; j++) { + if (offset+2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + srec->data[j] = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + cksum += srec->data[j]; + } + + /* cksum */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + srec->cksum = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + rc = 0xff - cksum; + return rc; +} + + +static int srec2b(char * infile, FILE * inf, + unsigned char * outbuf, int bufsize) +{ + char buffer [ MAX_LINE_LEN ]; + unsigned char * buf; + unsigned int nextaddr, baseaddr, maxaddr; + int i; + int lineno; + int len; + struct ihexrec srec; + int rc; + int reccount; + unsigned char datarec; + + char * msg = 0; + + lineno = 0; + buf = outbuf; + baseaddr = 0; + maxaddr = 0; + reccount = 0; + + while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { + lineno++; + len = strlen(buffer); + if (buffer[len-1] == '\n') + buffer[--len] = 0; + if (buffer[0] != 0x53) + continue; + rc = srec_readrec(&srec, buffer); + + if (rc < 0) { + fprintf(stderr, "%s: ERROR: invalid record at line %d of \"%s\"\n", + progname, lineno, infile); + return -1; + } + else if (rc != srec.cksum) { + fprintf(stderr, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n", + progname, lineno, infile); + fprintf(stderr, "%s: checksum=0x%02x, computed checksum=0x%02x\n", + progname, srec.cksum, rc); + return -1; + } + + datarec=0; + switch (srec.rectyp) { + case 0x30: /* S0 - header record*/ + /* skip */ + break; + + case 0x31: /* S1 - 16 bit address data record */ + datarec=1; + msg="%s: ERROR: address 0x%04x out of range at line %d of %s\n"; + break; + + case 0x32: /* S2 - 24 bit address data record */ + datarec=1; + msg="%s: ERROR: address 0x%06x out of range at line %d of %s\n"; + break; + + case 0x33: /* S3 - 32 bit address data record */ + datarec=1; + msg="%s: ERROR: address 0x%08x out of range at line %d of %s\n"; + break; + + case 0x34: /* S4 - symbol record (LSI extension) */ + fprintf(stderr, + "%s: ERROR: not supported record at line %d of %s\n", + progname, lineno, infile); + return -1; + + case 0x35: /* S5 - count of S1,S2 and S3 records previously tx'd */ + if (srec.loadofs != reccount){ + fprintf(stderr, + "%s: ERROR: count of transmitted data records mismatch " + "at line %d of \"%s\"\n", + progname, lineno, infile); + fprintf(stderr, "%s: transmitted data records= %d, expected " + "value= %d\n", + progname, reccount, srec.loadofs); + return -1; + } + break; + + case 0x37: /* S7 Record - end record for 32 bit address data */ + case 0x38: /* S8 Record - end record for 24 bit address data */ + case 0x39: /* S9 Record - end record for 16 bit address data */ + return maxaddr; + + default: + fprintf(stderr, + "%s: ERROR: don't know how to deal with rectype S%d " + "at line %d of %s\n", + progname, srec.rectyp, lineno, infile); + return -1; + } + + if (datarec == 1) { + nextaddr = srec.loadofs + baseaddr; + if (nextaddr + srec.reclen > bufsize) { + fprintf(stderr, msg, progname, nextaddr+srec.reclen, lineno, infile); + return -1; + } + for (i=0; i maxaddr) + maxaddr = nextaddr+srec.reclen; + reccount++; + } + + } + + fprintf(stderr, + "%s: WARNING: no end of file record found for Motorola S-Records " + "file \"%s\"\n", + progname, infile); + + return maxaddr; +} + +/* + * Simple itoa() implementation. Caller needs to allocate enough + * space in buf. Only positive integers are handled. + */ +static char *itoa_simple(int n, char *buf, int base) +{ + div_t q; + char c, *cp, *cp2; + + cp = buf; + /* + * Divide by base until the number disappeared, but ensure at least + * one digit will be emitted. + */ + do { + q = div(n, base); + n = q.quot; + if (q.rem >= 10) + c = q.rem - 10 + 'a'; + else + c = q.rem + '0'; + *cp++ = c; + } while (q.quot != 0); + + /* Terminate the string. */ + *cp-- = '\0'; + + /* Now revert the result string. */ + cp2 = buf; + while (cp > cp2) { + c = *cp; + *cp-- = *cp2; + *cp2++ = c; + } + + return buf; +} + + + +static int fileio_rbin(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size) +{ + int rc; + + switch (fio->op) { + case FIO_READ: + rc = fread(buf, 1, size, f); + break; + case FIO_WRITE: + rc = fwrite(buf, 1, size, f); + break; + default: + fprintf(stderr, "%s: fileio: invalid operation=%d\n", + progname, fio->op); + return -1; + } + + if (rc < 0 || (fio->op == FIO_WRITE && rc < size)) { + fprintf(stderr, + "%s: %s error %s %s: %s; %s %d of the expected %d bytes\n", + progname, fio->iodesc, fio->dir, filename, strerror(errno), + fio->rw, rc, size); + return -1; + } + + return rc; +} + + +static int fileio_imm(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size) +{ + int rc = 0; + char * e, * p; + unsigned long b; + int loc; + + switch (fio->op) { + case FIO_READ: + loc = 0; + p = strtok(filename, " ,"); + while (p != NULL && loc < size) { + b = strtoul(p, &e, 0); + /* check for binary formated (0b10101001) strings */ + b = (strncmp (p, "0b", 2))? + strtoul (p, &e, 0): + strtoul (p + 2, &e, 2); + if (*e != 0) { + fprintf(stderr, + "%s: invalid byte value (%s) specified for immediate mode\n", + progname, p); + return -1; + } + buf[loc++] = b; + p = strtok(NULL, " ,"); + rc = loc; + } + break; + default: + fprintf(stderr, "%s: fileio: invalid operation=%d\n", + progname, fio->op); + return -1; + } + + if (rc < 0 || (fio->op == FIO_WRITE && rc < size)) { + fprintf(stderr, + "%s: %s error %s %s: %s; %s %d of the expected %d bytes\n", + progname, fio->iodesc, fio->dir, filename, strerror(errno), + fio->rw, rc, size); + return -1; + } + + return rc; +} + + +static int fileio_ihex(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size) +{ + int rc; + + switch (fio->op) { + case FIO_WRITE: + rc = b2ihex(buf, size, 32, 0, filename, f); + if (rc < 0) { + return -1; + } + break; + + case FIO_READ: + rc = ihex2b(filename, f, buf, size); + if (rc < 0) + return -1; + break; + + default: + fprintf(stderr, "%s: invalid Intex Hex file I/O operation=%d\n", + progname, fio->op); + return -1; + break; + } + + return rc; +} + + +static int fileio_srec(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size) +{ + int rc; + + switch (fio->op) { + case FIO_WRITE: + rc = b2srec(buf, size, 32, 0, filename, f); + if (rc < 0) { + return -1; + } + break; + + case FIO_READ: + rc = srec2b(filename, f, buf, size); + if (rc < 0) + return -1; + break; + + default: + fprintf(stderr, "%s: ERROR: invalid Motorola S-Records file I/O " + "operation=%d\n", + progname, fio->op); + return -1; + break; + } + + return rc; +} + + +static int fileio_num(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size, + FILEFMT fmt) +{ + const char *prefix; + char cbuf[20]; + int base, i, num; + + switch (fmt) { + case FMT_HEX: + prefix = "0x"; + base = 16; + break; + + default: + case FMT_DEC: + prefix = ""; + base = 10; + break; + + case FMT_OCT: + prefix = "0"; + base = 8; + break; + + case FMT_BIN: + prefix = "0b"; + base = 2; + break; + + } + + switch (fio->op) { + case FIO_WRITE: + break; + default: + fprintf(stderr, "%s: fileio: invalid operation=%d\n", + progname, fio->op); + return -1; + } + + for (i = 0; i < size; i++) { + if (i > 0) { + if (putc(',', f) == EOF) + goto writeerr; + } + num = (unsigned int)buf[i]; + /* + * For a base of 8 and a value < 8 to convert, don't write the + * prefix. The conversion will be indistinguishable from a + * decimal one then. + */ + if (prefix[0] != '\0' && !(base == 8 && num < 8)) { + if (fputs(prefix, f) == EOF) + goto writeerr; + } + itoa_simple(num, cbuf, base); + if (fputs(cbuf, f) == EOF) + goto writeerr; + } + if (putc('\n', f) == EOF) + goto writeerr; + + return 0; + + writeerr: + fprintf(stderr, "%s: error writing to %s: %s\n", + progname, filename, strerror(errno)); + return -1; +} + + +int fileio_setparms(int op, struct fioparms * fp) +{ + fp->op = op; + + switch (op) { + case FIO_READ: + fp->mode = "r"; + fp->iodesc = "input"; + fp->dir = "from"; + fp->rw = "read"; + break; + + case FIO_WRITE: + fp->mode = "w"; + fp->iodesc = "output"; + fp->dir = "to"; + fp->rw = "wrote"; + break; + + default: + fprintf(stderr, "%s: invalid I/O operation %d\n", + progname, op); + return -1; + break; + } + + return 0; +} + + + +static int fmt_autodetect(char * fname) +{ + FILE * f; + unsigned char buf[MAX_LINE_LEN]; + int i; + int len; + int found; + + f = fopen(fname, "r"); + if (f == NULL) { + fprintf(stderr, "%s: error opening %s: %s\n", + progname, fname, strerror(errno)); + return -1; + } + + while (fgets((char *)buf, MAX_LINE_LEN, f)!=NULL) { + buf[MAX_LINE_LEN-1] = 0; + len = strlen((char *)buf); + if (buf[len-1] == '\n') + buf[--len] = 0; + + /* check for binary data */ + found = 0; + for (i=0; i 127) { + found = 1; + break; + } + } + if (found) { + fclose(f); + return FMT_RBIN; + } + + /* check for lines that look like intel hex */ + if ((buf[0] == ':') && (len >= 11)) { + found = 1; + for (i=1; i= 10) && isdigit(buf[1])) { + found = 1; + for (i=1; idesc); + return -1; + } + + rc = fileio_setparms(op, &fio); + if (rc < 0) + return -1; + + /* point at the requested memory buffer */ + buf = mem->buf; + if (fio.op == FIO_READ) + size = mem->size; + + if (fio.op == FIO_READ) { + /* 0xff fill unspecified memory */ + memset(buf, 0xff, size); + } + + using_stdio = 0; + + if (strcmp(filename, "-")==0) { + if (fio.op == FIO_READ) { + fname = ""; + f = stdin; + } + else { + fname = ""; + f = stdout; + } + using_stdio = 1; + } + else { + fname = filename; + f = NULL; + } + + if (format == FMT_AUTO) { + if (using_stdio) { + fprintf(stderr, + "%s: can't auto detect file format when using stdin/out.\n" + " Please specify a file format using the -f option and try again.\n", + progname); + exit(1); + } + + format = fmt_autodetect(fname); + if (format < 0) { + fprintf(stderr, + "%s: can't determine file format for %s, specify explicitly\n", + progname, fname); + return -1; + } + + if (quell_progress < 2) { + fprintf(stderr, "%s: %s file %s auto detected as %s\n", + progname, fio.iodesc, fname, fmtstr(format)); + } + } + +#if defined(WIN32NATIVE) + /* Open Raw Binary format in binary mode on Windows.*/ + if(format == FMT_RBIN) + { + if(fio.op == FIO_READ) + { + fio.mode = "rb"; + } + if(fio.op == FIO_WRITE) + { + fio.mode = "wb"; + } + } +#endif + + if (format != FMT_IMM) { + if (!using_stdio) { + f = fopen(fname, fio.mode); + if (f == NULL) { + fprintf(stderr, "%s: can't open %s file %s: %s\n", + progname, fio.iodesc, fname, strerror(errno)); + return -1; + } + } + } + + switch (format) { + case FMT_IHEX: + rc = fileio_ihex(&fio, fname, f, buf, size); + break; + + case FMT_SREC: + rc = fileio_srec(&fio, fname, f, buf, size); + break; + + case FMT_RBIN: + rc = fileio_rbin(&fio, fname, f, buf, size); + break; + + case FMT_IMM: + rc = fileio_imm(&fio, fname, f, buf, size); + break; + + case FMT_HEX: + case FMT_DEC: + case FMT_OCT: + case FMT_BIN: + rc = fileio_num(&fio, fname, f, buf, size, format); + break; + + default: + fprintf(stderr, "%s: invalid %s file format: %d\n", + progname, fio.iodesc, format); + return -1; + } + + if (rc > 0) { + if ((op == FIO_READ) && (strcasecmp(mem->desc, "flash") == 0)) { + /* + * if we are reading flash, just mark the size as being the + * highest non-0xff byte + */ + rc = avr_mem_hiaddr(mem); + } + } + if (format != FMT_IMM && !using_stdio) { + fclose(f); + } + + return rc; +} + diff --git a/avrdude/fileio.h b/avrdude/fileio.h new file mode 100644 index 00000000..2fe3f209 --- /dev/null +++ b/avrdude/fileio.h @@ -0,0 +1,65 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef fileio_h +#define fileio_h + +typedef enum { + FMT_AUTO, + FMT_SREC, + FMT_IHEX, + FMT_RBIN, + FMT_IMM, + FMT_HEX, + FMT_DEC, + FMT_OCT, + FMT_BIN +} FILEFMT; + +struct fioparms { + int op; + char * mode; + char * iodesc; + char * dir; + char * rw; +}; + +enum { + FIO_READ, + FIO_WRITE +}; + +#ifdef __cplusplus +extern "C" { +#endif + +char * fmtstr(FILEFMT format); + +int fileio_setparms(int op, struct fioparms * fp); + +int fileio(int op, char * filename, FILEFMT format, + struct avrpart * p, char * memtype, int size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/freebsd_ppi.h b/avrdude/freebsd_ppi.h new file mode 100644 index 00000000..0885fc43 --- /dev/null +++ b/avrdude/freebsd_ppi.h @@ -0,0 +1,40 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef freebsd_ppi_h +#define freebsd_ppi_h + +#include + +#define ppi_claim(fd) {} + +#define ppi_release(fd) {} + +#define DO_PPI_READ(fd, reg, valp) \ + (void)ioctl(fd, \ + (reg) == PPIDATA? PPIGDATA: ((reg) == PPICTRL? PPIGCTRL: PPIGSTATUS), \ + valp) +#define DO_PPI_WRITE(fd, reg, valp) \ + (void)ioctl(fd, \ + (reg) == PPIDATA? PPISDATA: ((reg) == PPICTRL? PPISCTRL: PPISSTATUS), \ + valp) + +#endif /* freebsd_ppi_h */ diff --git a/avrdude/jtagmkI.c b/avrdude/jtagmkI.c new file mode 100644 index 00000000..cb1f84a6 --- /dev/null +++ b/avrdude/jtagmkI.c @@ -0,0 +1,1404 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005, 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel JTAG ICE (mkI) programmer + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "crc16.h" +#include "pgm.h" +#include "jtagmkI_private.h" +#include "serial.h" + +/* + * Private data for this programmer. + */ +struct pdata +{ + int initial_baudrate; + + /* + * See jtagmkI_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ + unsigned char *flash_pagecache; + unsigned long flash_pageaddr; + unsigned int flash_pagesize; + + unsigned char *eeprom_pagecache; + unsigned long eeprom_pageaddr; + unsigned int eeprom_pagesize; + + int prog_enabled; /* Cached value of PROGRAMMING status. */ +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +/* + * The OCDEN fuse is bit 7 of the high fuse (hfuse). In order to + * perform memory operations on MTYPE_SPM and MTYPE_EEPROM, OCDEN + * needs to be programmed. + * + * OCDEN should probably rather be defined via the configuration, but + * if this ever changes to a different fuse byte for one MCU, quite + * some code here needs to be generalized anyway. + */ +#define OCDEN (1 << 7) + +/* + * Table of baud rates supported by the mkI ICE, accompanied by their + * internal parameter value. + * + * 19200 is the initial value of the ICE after powerup, and virtually + * all connections then switch to 115200. As the table is also used + * to try connecting at startup, we keep these two entries on top to + * speedup the program start. + */ +const static struct { + long baud; + unsigned char val; +} baudtab[] = { + { 19200L, 0xfa }, + { 115200L, 0xff }, + { 9600L, 0xf4 }, + { 38400L, 0xfd }, + { 57600L, 0xfe }, +/* { 14400L, 0xf8 }, */ /* not supported by serial driver */ +}; + +static int jtagmkI_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value); +static int jtagmkI_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data); +static int jtagmkI_set_sck_period(PROGRAMMER * pgm, double v); +static int jtagmkI_getparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value); +static int jtagmkI_setparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char value); +static void jtagmkI_print_parms1(PROGRAMMER * pgm, const char * p); + +static int jtagmkI_resync(PROGRAMMER *pgm, int maxtries, int signon); + +static void jtagmkI_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: jtagmkI_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void jtagmkI_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + + +static void +u32_to_b3(unsigned char *b, unsigned long l) +{ + b[2] = l & 0xff; + b[1] = (l >> 8) & 0xff; + b[0] = (l >> 16) & 0xff; +} + +static void +u16_to_b2(unsigned char *b, unsigned short l) +{ + b[0] = l & 0xff; + b[1] = (l >> 8) & 0xff; +} + +static void jtagmkI_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + int i; + + if (verbose >= 4) { + fprintf(stderr, "Raw message:\n"); + + for (i = 0; i < len; i++) { + fprintf(stderr, "0x%02x ", data[i]); + if (i % 16 == 15) + putc('\n', stderr); + else + putchar(' '); + } + if (i % 16 != 0) + putc('\n', stderr); + } + + switch (data[0]) { + case RESP_OK: + fprintf(stderr, "OK\n"); + break; + + case RESP_FAILED: + fprintf(stderr, "FAILED\n"); + break; + + case RESP_BREAK: + fprintf(stderr, "breakpoint hit\n"); + break; + + case RESP_INFO: + fprintf(stderr, "IDR dirty\n"); + break; + + case RESP_SYNC_ERROR: + fprintf(stderr, "Synchronization lost\n"); + break; + + case RESP_SLEEP: + fprintf(stderr, "sleep instruction hit\n"); + break; + + case RESP_POWER: + fprintf(stderr, "target power lost\n"); + + default: + fprintf(stderr, "unknown message 0x%02x\n", data[0]); + } + + putc('\n', stderr); +} + + +static int jtagmkI_send(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + unsigned char *buf; + + if (verbose >= 3) + fprintf(stderr, "\n%s: jtagmkI_send(): sending %u bytes\n", + progname, (unsigned int)len); + + if ((buf = malloc(len + 2)) == NULL) + { + fprintf(stderr, "%s: jtagmkI_send(): out of memory", + progname); + exit(1); + } + + memcpy(buf, data, len); + buf[len] = ' '; /* "CRC" */ + buf[len + 1] = ' '; /* EOP */ + + if (serial_send(&pgm->fd, buf, len + 2) != 0) { + fprintf(stderr, + "%s: jtagmkI_send(): failed to send command to serial port\n", + progname); + exit(1); + } + + free(buf); + + return 0; +} + +static void jtagmkI_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len) +{ + if (serial_recv(&pgm->fd, buf, len) != 0) { + fprintf(stderr, + "\n%s: jtagmkI_recv(): failed to send command to serial port\n", + progname); + exit(1); + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkI_prmsg(pgm, buf, len); + } +} + + +static int jtagmkI_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(&pgm->fd, display); +} + + +static int jtagmkI_resync(PROGRAMMER * pgm, int maxtries, int signon) +{ + int tries; + unsigned char buf[4], resp[9]; + long otimeout = serial_recv_timeout; + + serial_recv_timeout = 200; + + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkI_resync()\n", progname); + + jtagmkI_drain(pgm, 0); + + for (tries = 0; tries < maxtries; tries++) { + + /* Get the sign-on information. */ + buf[0] = CMD_GET_SYNC; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_resync(): Sending sync command: ", + progname); + + if (serial_send(&pgm->fd, buf, 1) != 0) { + fprintf(stderr, + "\n%s: jtagmkI_resync(): failed to send command to serial port\n", + progname); + serial_recv_timeout = otimeout; + return -1; + } + if (serial_recv(&pgm->fd, resp, 1) == 0 && resp[0] == RESP_OK) { + if (verbose >= 2) + fprintf(stderr, "got RESP_OK\n"); + break; + } + + if (signon) { + /* + * The following is black magic, the idea has been taken from + * AVaRICE. + * + * Apparently, the ICE behaves differently right after a + * power-up vs. when reconnecting to an ICE that has already + * been worked with. The undocumented 'E' command (or + * subcommand) occasionally helps in getting the connection into + * sync. + */ + buf[0] = CMD_GET_SIGNON; + buf[1] = 'E'; + buf[2] = ' '; + buf[3] = ' '; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_resync(): Sending sign-on command: ", + progname); + + if (serial_send(&pgm->fd, buf, 4) != 0) { + fprintf(stderr, + "\n%s: jtagmkI_resync(): failed to send command to serial port\n", + progname); + serial_recv_timeout = otimeout; + return -1; + } + if (serial_recv(&pgm->fd, resp, 9) == 0 && resp[0] == RESP_OK) { + if (verbose >= 2) + fprintf(stderr, "got RESP_OK\n"); + break; + } + } + } + if (tries >= maxtries) { + if (verbose >= 2) + fprintf(stderr, + "%s: jtagmkI_resync(): " + "timeout/error communicating with programmer\n", + progname); + serial_recv_timeout = otimeout; + return -1; + } + + serial_recv_timeout = otimeout; + return 0; +} + +static int jtagmkI_getsync(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[9]; + + if (jtagmkI_resync(pgm, 5, 1) < 0) { + jtagmkI_drain(pgm, 0); + return -1; + } + + jtagmkI_drain(pgm, 0); + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_getsync(): Sending sign-on command: ", + progname); + + buf[0] = CMD_GET_SIGNON; + jtagmkI_send(pgm, buf, 1); + jtagmkI_recv(pgm, resp, 9); + if (verbose >= 2) { + resp[8] = '\0'; + fprintf(stderr, "got %s\n", resp + 1); + } + + return 0; +} + +/* + * issue the 'chip erase' command to the AVR device + */ +static int jtagmkI_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[1], resp[2]; + + buf[0] = CMD_CHIP_ERASE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_chip_erase(): Sending chip erase command: ", + progname); + jtagmkI_send(pgm, buf, 1); + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_chip_erase(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + pgm->initialize(pgm, p); + + return 0; +} + +static void jtagmkI_set_devdescr(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char resp[2]; + LNODEID ln; + AVRMEM * m; + struct { + unsigned char cmd; + struct device_descriptor dd; + } sendbuf; + + memset(&sendbuf, 0, sizeof sendbuf); + sendbuf.cmd = CMD_SET_DEVICE_DESCRIPTOR; + sendbuf.dd.ucSPMCRAddress = p->spmcr; + sendbuf.dd.ucRAMPZAddress = p->rampz; + sendbuf.dd.ucIDRAddress = p->idr; + for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { + m = ldata(ln); + if (strcmp(m->desc, "flash") == 0) { + PDATA(pgm)->flash_pagesize = m->page_size; + u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize); + } else if (strcmp(m->desc, "eeprom") == 0) { + sendbuf.dd.ucEepromPageSize = PDATA(pgm)->eeprom_pagesize = m->page_size; + } + } + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_set_devdescr(): " + "Sending set device descriptor command: ", + progname); + jtagmkI_send(pgm, (unsigned char *)&sendbuf, sizeof(sendbuf)); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_set_devdescr(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } +} + +/* + * Reset the target. + */ +static int jtagmkI_reset(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + buf[0] = CMD_RESET; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_reset(): Sending reset command: ", + progname); + jtagmkI_send(pgm, buf, 1); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_reset(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + return 0; +} + +static int jtagmkI_program_enable_dummy(PROGRAMMER * pgm, AVRPART * p) +{ + + return 0; +} + +static int jtagmkI_program_enable(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + if (PDATA(pgm)->prog_enabled) + return 0; + + buf[0] = CMD_ENTER_PROGMODE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_program_enable(): " + "Sending enter progmode command: ", + progname); + jtagmkI_send(pgm, buf, 1); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_program_enable(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + PDATA(pgm)->prog_enabled = 1; + + return 0; +} + +static int jtagmkI_program_disable(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + if (!PDATA(pgm)->prog_enabled) + return 0; + + if (pgm->fd.ifd != -1) { + buf[0] = CMD_LEAVE_PROGMODE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_program_disable(): " + "Sending leave progmode command: ", + progname); + jtagmkI_send(pgm, buf, 1); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_program_disable(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + } + PDATA(pgm)->prog_enabled = 0; + + return 0; +} + +static unsigned char jtagmkI_get_baud(long baud) +{ + int i; + + for (i = 0; i < sizeof baudtab / sizeof baudtab[0]; i++) + if (baud == baudtab[i].baud) + return baudtab[i].val; + + return 0; +} + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + AVRMEM hfuse; + unsigned char cmd[1], resp[5]; + unsigned char b; + + if (!(p->flags & AVRPART_HAS_JTAG)) { + fprintf(stderr, "%s: jtagmkI_initialize(): part %s has no JTAG interface\n", + progname, p->desc); + return -1; + } + + jtagmkI_drain(pgm, 0); + + if ((serdev->flags & SERDEV_FL_CANSETSPEED) && PDATA(pgm)->initial_baudrate != pgm->baudrate) { + if ((b = jtagmkI_get_baud(pgm->baudrate)) == 0) { + fprintf(stderr, "%s: jtagmkI_initialize(): unsupported baudrate %d\n", + progname, pgm->baudrate); + } else { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_initialize(): " + "trying to set baudrate to %d\n", + progname, pgm->baudrate); + if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) { + PDATA(pgm)->initial_baudrate = pgm->baudrate; /* don't adjust again later */ + serial_setspeed(&pgm->fd, pgm->baudrate); + } + } + } + + if (pgm->bitclock != 0.0) { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_initialize(): " + "trying to set JTAG clock period to %.1f us\n", + progname, pgm->bitclock); + if (jtagmkI_set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + cmd[0] = CMD_STOP; + jtagmkI_send(pgm, cmd, 1); + jtagmkI_recv(pgm, resp, 5); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_initialize(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + /* + * Must set the device descriptor before entering programming mode. + */ + jtagmkI_set_devdescr(pgm, p); + + jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_LOW, PDATA(pgm)->flash_pagesize & 0xff); + jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_HIGH, PDATA(pgm)->flash_pagesize >> 8); + jtagmkI_setparm(pgm, PARM_EEPROM_PAGESIZE, PDATA(pgm)->eeprom_pagesize & 0xff); + + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", + progname); + return -1; + } + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", + progname); + free(PDATA(pgm)->flash_pagecache); + return -1; + } + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + + if (jtagmkI_reset(pgm) < 0) + return -1; + + strcpy(hfuse.desc, "hfuse"); + if (jtagmkI_read_byte(pgm, p, &hfuse, 1, &b) < 0) + return -1; + if ((b & OCDEN) != 0) + fprintf(stderr, + "%s: jtagmkI_initialize(): warning: OCDEN fuse not programmed, " + "single-byte EEPROM updates not possible\n", + progname); + + return 0; +} + + +static void jtagmkI_disable(PROGRAMMER * pgm) +{ + + free(PDATA(pgm)->flash_pagecache); + PDATA(pgm)->flash_pagecache = NULL; + free(PDATA(pgm)->eeprom_pagecache); + PDATA(pgm)->eeprom_pagecache = NULL; + + (void)jtagmkI_program_disable(pgm); +} + +static void jtagmkI_enable(PROGRAMMER * pgm) +{ + return; +} + + +static int jtagmkI_open(PROGRAMMER * pgm, char * port) +{ + size_t i; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_open()\n", progname); + + strcpy(pgm->port, port); + PDATA(pgm)->initial_baudrate = -1L; + + for (i = 0; i < sizeof(baudtab) / sizeof(baudtab[0]); i++) { + if (verbose >= 2) + fprintf(stderr, + "%s: jtagmkI_open(): trying to sync at baud rate %ld:\n", + progname, baudtab[i].baud); + if (serial_open(port, baudtab[i].baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkI_drain(pgm, 0); + + if (jtagmkI_getsync(pgm) == 0) { + PDATA(pgm)->initial_baudrate = baudtab[i].baud; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_open(): succeeded\n", progname); + return 0; + } + + serial_close(&pgm->fd); + } + + fprintf(stderr, + "%s: jtagmkI_open(): failed to synchronize to ICE\n", + progname); + pgm->fd.ifd = -1; + + return -1; +} + + +static void jtagmkI_close(PROGRAMMER * pgm) +{ + unsigned char b; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_close()\n", progname); + + /* + * Revert baud rate to what it used to be when we started. This + * appears to make AVR Studio happier when it is about to access the + * ICE later on. + */ + if ((serdev->flags & SERDEV_FL_CANSETSPEED) && PDATA(pgm)->initial_baudrate != pgm->baudrate) { + if ((b = jtagmkI_get_baud(PDATA(pgm)->initial_baudrate)) == 0) { + fprintf(stderr, "%s: jtagmkI_close(): unsupported baudrate %d\n", + progname, PDATA(pgm)->initial_baudrate); + } else { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_close(): " + "trying to set baudrate to %d\n", + progname, PDATA(pgm)->initial_baudrate); + if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) { + serial_setspeed(&pgm->fd, pgm->baudrate); + } + } + } + + if (pgm->fd.ifd != -1) { + serial_close(&pgm->fd); + } + + pgm->fd.ifd = -1; +} + + +static int jtagmkI_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int addr, block_size, send_size, tries; + unsigned char cmd[6], *datacmd; + unsigned char resp[2]; + int is_flash = 0; + long otimeout = serial_recv_timeout; +#define MAXTRIES 3 + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_write(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + if (jtagmkI_program_enable(pgm) < 0) + return -1; + + if (page_size == 0) page_size = 256; + + if (page_size > 256) { + fprintf(stderr, "%s: jtagmkI_paged_write(): page size %d too large\n", + progname, page_size); + return -1; + } + + if ((datacmd = malloc(page_size + 1)) == NULL) { + fprintf(stderr, "%s: jtagmkI_paged_write(): Out of memory\n", + progname); + return -1; + } + + cmd[0] = CMD_WRITE_MEM; + if (strcmp(m->desc, "flash") == 0) { + cmd[1] = MTYPE_FLASH_PAGE; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->flash_pagesize; + is_flash = 1; + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM_PAGE; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->eeprom_pagesize; + } + datacmd[0] = CMD_DATA; + + serial_recv_timeout = 1000; + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + tries = 0; + again: + + if (tries != 0 && jtagmkI_resync(pgm, 2000, 0) < 0) { + fprintf(stderr, + "%s: jtagmkI_paged_write(): sync loss, retries exhausted\n", + progname); + return -1; + } + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkI_paged_write(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + /* We always write full pages. */ + send_size = page_size; + if (is_flash) { + cmd[2] = send_size / 2 - 1; + u32_to_b3(cmd + 3, addr / 2); + } else { + cmd[2] = send_size - 1; + u32_to_b3(cmd + 3, addr); + } + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_write(): " + "Sending write memory command: ", + progname); + + /* First part, send the write command. */ + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_paged_write(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + if (tries++ < MAXTRIES) + goto again; + serial_recv_timeout = otimeout; + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + /* + * The JTAG ICE will refuse to write anything but a full page, at + * least for the flash ROM. If a partial page has been requested, + * set the remainder to 0xff. (Maybe we should rather read back + * the existing contents instead before? Doesn't matter much, as + * bits cannot be written to 1 anyway.) + */ + memset(datacmd + 1, 0xff, page_size); + memcpy(datacmd + 1, m->buf + addr, block_size); + + /* Second, send the data command. */ + jtagmkI_send(pgm, datacmd, send_size + 1); + jtagmkI_recv(pgm, resp, 2); + if (resp[1] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_paged_write(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + if (tries++ < MAXTRIES) + goto again; + serial_recv_timeout = otimeout; + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + } + + free(datacmd); + serial_recv_timeout = otimeout; + +#undef MAXTRIES + return n_bytes; +} + +static int jtagmkI_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int addr, block_size, read_size, is_flash = 0, tries; + unsigned char cmd[6], resp[256 * 2 + 3]; + long otimeout = serial_recv_timeout; +#define MAXTRIES 3 + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_load(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + if (jtagmkI_program_enable(pgm) < 0) + return -1; + + page_size = m->readsize; + + cmd[0] = CMD_READ_MEM; + if (strcmp(m->desc, "flash") == 0) { + cmd[1] = MTYPE_FLASH_PAGE; + is_flash = 1; + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM_PAGE; + } + + if (page_size > (is_flash? 512: 256)) { + fprintf(stderr, "%s: jtagmkI_paged_load(): page size %d too large\n", + progname, page_size); + return -1; + } + + serial_recv_timeout = 1000; + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + tries = 0; + again: + if (tries != 0 && jtagmkI_resync(pgm, 2000, 0) < 0) { + fprintf(stderr, + "%s: jtagmkI_paged_load(): sync loss, retries exhausted\n", + progname); + return -1; + } + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkI_paged_load(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + if (is_flash) { + read_size = 2 * ((block_size + 1) / 2); /* round up */ + cmd[2] = read_size / 2 - 1; + u32_to_b3(cmd + 3, addr / 2); + } else { + read_size = page_size; + cmd[2] = page_size - 1; + u32_to_b3(cmd + 3, addr); + } + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_load(): Sending read memory command: ", + progname); + + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, read_size + 3); + + if (resp[read_size + 3 - 1] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_paged_load(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[read_size + 3 - 1]); + if (tries++ < MAXTRIES) + goto again; + + serial_recv_timeout = otimeout; + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + memcpy(m->buf + addr, resp + 1, block_size); + } + serial_recv_timeout = otimeout; + +#undef MAXTRIES + return n_bytes; +} + +static int jtagmkI_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + unsigned char cmd[6]; + unsigned char resp[256 * 2 + 3], *cache_ptr = NULL; + unsigned long paddr = 0UL, *paddr_ptr = NULL; + unsigned int pagesize = 0; + int respsize = 3 + 1; + int is_flash = 0; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_read_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + if (jtagmkI_program_enable(pgm) < 0) + return -1; + + cmd[0] = CMD_READ_MEM; + + if (strcmp(mem->desc, "flash") == 0) { + cmd[1] = MTYPE_FLASH_PAGE; + pagesize = mem->page_size; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; + is_flash = 1; + } else if (strcmp(mem->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM_PAGE; + pagesize = mem->page_size; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; + } else if (strcmp(mem->desc, "lfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 0; + } else if (strcmp(mem->desc, "hfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 2; + } else if (strcmp(mem->desc, "lock") == 0) { + cmd[1] = MTYPE_LOCK_BITS; + } else if (strcmp(mem->desc, "calibration") == 0) { + cmd[1] = MTYPE_OSCCAL_BYTE; + } else if (strcmp(mem->desc, "signature") == 0) { + cmd[1] = MTYPE_SIGN_JTAG; + } + + /* + * To improve the read speed, we used paged reads for flash and + * EEPROM, and cache the results in a page cache. + * + * Page cache validation is based on "{flash,eeprom}_pageaddr" + * (holding the base address of the most recent cache fill + * operation). This variable is set to (unsigned long)-1L when the + * cache needs to be invalidated. + */ + if (pagesize && paddr == *paddr_ptr) { + *value = cache_ptr[addr & (pagesize - 1)]; + return 0; + } + + if (pagesize) { + if (is_flash) { + cmd[2] = pagesize / 2 - 1; + u32_to_b3(cmd + 3, paddr / 2); + } else { + cmd[2] = pagesize - 1; + u32_to_b3(cmd + 3, paddr); + } + respsize = 3 + pagesize; + } else { + if (cmd[1] == MTYPE_FUSE_BITS) { + /* + * The mkI ICE has a bug where it doesn't read efuse correctly + * when reading it as a single byte @offset 2, while reading all + * fuses at once does work. + */ + cmd[2] = 3 - 1; + u32_to_b3(cmd + 3, 0); + respsize = 3 + 3; + } else { + cmd[2] = 1 - 1; + u32_to_b3(cmd + 3, addr); + } + } + + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, respsize); + + if (resp[respsize - 1] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_read_byte(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[respsize - 1]); + exit(1); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + if (pagesize) { + *paddr_ptr = paddr; + memcpy(cache_ptr, resp + 1, pagesize); + *value = cache_ptr[addr & (pagesize - 1)]; + } else if (cmd[1] == MTYPE_FUSE_BITS) { + /* extract the desired fuse */ + *value = resp[1 + addr]; + } else + *value = resp[1]; + + return 0; +} + +static int jtagmkI_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + unsigned char cmd[6], datacmd[1 * 2 + 1]; + unsigned char resp[1], writedata; + int len, need_progmode = 1; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_write_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + writedata = data; + cmd[0] = CMD_WRITE_MEM; + if (strcmp(mem->desc, "flash") == 0) { + cmd[1] = MTYPE_SPM; + need_progmode = 0; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + } else if (strcmp(mem->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM; + need_progmode = 0; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + } else if (strcmp(mem->desc, "lfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 0; + } else if (strcmp(mem->desc, "hfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 2; + } else if (strcmp(mem->desc, "lock") == 0) { + cmd[1] = MTYPE_LOCK_BITS; + } else if (strcmp(mem->desc, "calibration") == 0) { + cmd[1] = MTYPE_OSCCAL_BYTE; + } else if (strcmp(mem->desc, "signature") == 0) { + cmd[1] = MTYPE_SIGN_JTAG; + } + + if (need_progmode) { + if (jtagmkI_program_enable(pgm) < 0) + return -1; + } else { + if (jtagmkI_program_disable(pgm) < 0) + return -1; + } + + cmd[2] = 1 - 1; + if (cmd[1] == MTYPE_SPM) { + /* + * Flash is word-addressed, but we cannot handle flash anyway + * here, as it needs to be written one page at a time... + */ + u32_to_b3(cmd + 3, addr / 2); + } else { + u32_to_b3(cmd + 3, addr); + } + /* First part, send the write command. */ + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_write_byte(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + /* Now, send the data buffer. */ + datacmd[0] = CMD_DATA; + if (cmd[1] == MTYPE_SPM) { + len = 3; + if ((addr & 1) != 0) { + datacmd[1] = 0; + datacmd[2] = writedata; + } else { + datacmd[1] = writedata; + datacmd[2] = 0; + } + } else { + len = 2; + datacmd[1] = writedata; + } + jtagmkI_send(pgm, datacmd, len); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_write_byte(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + return 0; +} + + +/* + * Set the JTAG clock. The actual frequency is quite a bit of + * guesswork, based on the values claimed by AVR Studio. Inside the + * JTAG ICE, the value is the delay count of a delay loop between the + * JTAG clock edges. A count of 0 bypasses the delay loop. + * + * As the STK500 expresses it as a period length (and we actualy do + * program a period length as well), we rather call it by that name. + */ +static int jtagmkI_set_sck_period(PROGRAMMER * pgm, double v) +{ + unsigned char dur; + + v = 1 / v; /* convert to frequency */ + if (v >= 1e6) + dur = JTAG_BITRATE_1_MHz; + else if (v >= 499e3) + dur = JTAG_BITRATE_500_kHz; + else if (v >= 249e3) + dur = JTAG_BITRATE_250_kHz; + else + dur = JTAG_BITRATE_125_kHz; + + return jtagmkI_setparm(pgm, PARM_CLOCK, dur); +} + + +/* + * Read an emulator parameter. The result is exactly one byte, + * multi-byte parameters get two different parameter names for + * their components. + */ +static int jtagmkI_getparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value) +{ + unsigned char buf[2], resp[3]; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_getparm()\n", progname); + + buf[0] = CMD_GET_PARAM; + buf[1] = parm; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_getparm(): " + "Sending get parameter command (parm 0x%02x): ", + progname, parm); + jtagmkI_send(pgm, buf, 2); + + jtagmkI_recv(pgm, resp, 3); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_getparm(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else if (resp[2] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_getparm(): " + "unknown parameter 0x%02x\n", + progname, parm); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK, value 0x%02x\n", resp[1]); + } + + *value = resp[1]; + + return 0; +} + +/* + * Write an emulator parameter. + */ +static int jtagmkI_setparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char value) +{ + unsigned char buf[3], resp[2]; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_setparm()\n", progname); + + buf[0] = CMD_SET_PARAM; + buf[1] = parm; + buf[2] = value; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_setparm(): " + "Sending set parameter command (parm 0x%02x): ", + progname, parm); + jtagmkI_send(pgm, buf, 3); + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_setparm(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + return 0; +} + + +static void jtagmkI_display(PROGRAMMER * pgm, const char * p) +{ + + unsigned char hw, fw; + + if (jtagmkI_getparm(pgm, PARM_HW_VERSION, &hw) < 0 || + jtagmkI_getparm(pgm, PARM_SW_VERSION, &fw) < 0) + return; + + fprintf(stderr, "%sICE hardware version: 0x%02x\n", p, hw); + fprintf(stderr, "%sICE firmware version: 0x%02x\n", p, fw); + + jtagmkI_print_parms1(pgm, p); + + return; +} + + +static void jtagmkI_print_parms1(PROGRAMMER * pgm, const char * p) +{ + unsigned char vtarget, jtag_clock; + const char *clkstr; + double clk; + + if (jtagmkI_getparm(pgm, PARM_OCD_VTARGET, &vtarget) < 0 || + jtagmkI_getparm(pgm, PARM_CLOCK, &jtag_clock) < 0) + return; + + switch ((unsigned)jtag_clock) { + case JTAG_BITRATE_1_MHz: + clkstr = "1 MHz"; + clk = 1e6; + break; + + case JTAG_BITRATE_500_kHz: + clkstr = "500 kHz"; + clk = 500e3; + break; + + case JTAG_BITRATE_250_kHz: + clkstr = "250 kHz"; + clk = 250e3; + break; + + case JTAG_BITRATE_125_kHz: + clkstr = "125 kHz"; + clk = 125e3; + break; + + default: + clkstr = "???"; + clk = 1e6; + } + + fprintf(stderr, "%sVtarget : %.1f V\n", p, + 6.25 * (unsigned)vtarget / 255.0); + fprintf(stderr, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, + 1.0e6 / clk); + + return; +} + + +static void jtagmkI_print_parms(PROGRAMMER * pgm) +{ + jtagmkI_print_parms1(pgm, ""); +} + + +void jtagmkI_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKI"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkI_initialize; + pgm->display = jtagmkI_display; + pgm->enable = jtagmkI_enable; + pgm->disable = jtagmkI_disable; + pgm->program_enable = jtagmkI_program_enable_dummy; + pgm->chip_erase = jtagmkI_chip_erase; + pgm->open = jtagmkI_open; + pgm->close = jtagmkI_close; + pgm->read_byte = jtagmkI_read_byte; + pgm->write_byte = jtagmkI_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkI_paged_write; + pgm->paged_load = jtagmkI_paged_load; + pgm->print_parms = jtagmkI_print_parms; + pgm->set_sck_period = jtagmkI_set_sck_period; + pgm->setup = jtagmkI_setup; + pgm->teardown = jtagmkI_teardown; + pgm->page_size = 256; +} diff --git a/avrdude/jtagmkI.h b/avrdude/jtagmkI.h new file mode 100644 index 00000000..d6669b11 --- /dev/null +++ b/avrdude/jtagmkI.h @@ -0,0 +1,36 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef jtagmkI_h +#define jtagmkI_h + +#ifdef __cplusplus +extern "C" { +#endif + +void jtagmkI_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/avrdude/jtagmkII.c b/avrdude/jtagmkII.c new file mode 100644 index 00000000..268b4198 --- /dev/null +++ b/avrdude/jtagmkII.c @@ -0,0 +1,3797 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005-2007 Joerg Wunsch + * + * Derived from stk500 code which is: + * Copyright (C) 2002-2004 Brian S. Dean + * Copyright (C) 2005 Erik Walthinsen + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel JTAG ICE mkII programmer + * + * The AVR Dragon also uses the same protocol, so it is handled here + * as well. + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "crc16.h" +#include "pgm.h" +#include "jtagmkII.h" +#include "jtagmkII_private.h" +#include "serial.h" +#include "usbdevs.h" + +/* + * Private data for this programmer. + */ +struct pdata +{ + unsigned short command_sequence; /* Next cmd seqno to issue. */ + + /* + * See jtagmkII_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ + unsigned char *flash_pagecache; + unsigned long flash_pageaddr; + unsigned int flash_pagesize; + + unsigned char *eeprom_pagecache; + unsigned long eeprom_pageaddr; + unsigned int eeprom_pagesize; + + int prog_enabled; /* Cached value of PROGRAMMING status. */ + unsigned char serno[6]; /* JTAG ICE serial number. */ + + /* JTAG chain stuff */ + unsigned char jtagchain[4]; + + /* The length of the device descriptor is firmware-dependent. */ + size_t device_descriptor_length; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +/* + * The OCDEN fuse is bit 7 of the high fuse (hfuse). In order to + * perform memory operations on MTYPE_SPM and MTYPE_EEPROM, OCDEN + * needs to be programmed. + * + * OCDEN should probably rather be defined via the configuration, but + * if this ever changes to a different fuse byte for one MCU, quite + * some code here needs to be generalized anyway. + */ +#define OCDEN (1 << 7) + +#define RC(x) { x, #x }, +static struct { + unsigned int code; + const char *descr; +} jtagresults[] = { + RC(RSP_DEBUGWIRE_SYNC_FAILED) + RC(RSP_FAILED) + RC(RSP_ILLEGAL_BREAKPOINT) + RC(RSP_ILLEGAL_COMMAND) + RC(RSP_ILLEGAL_EMULATOR_MODE) + RC(RSP_ILLEGAL_JTAG_ID) + RC(RSP_ILLEGAL_MCU_STATE) + RC(RSP_ILLEGAL_MEMORY_TYPE) + RC(RSP_ILLEGAL_MEMORY_RANGE) + RC(RSP_ILLEGAL_PARAMETER) + RC(RSP_ILLEGAL_POWER_STATE) + RC(RSP_ILLEGAL_VALUE) + RC(RSP_NO_TARGET_POWER) + RC(RSP_SET_N_PARAMETERS) +}; + +/* + * pgm->flag is marked as "for private use of the programmer". + * The following defines this programmer's use of that field. + */ +#define PGM_FL_IS_DW (0x0001) +#define PGM_FL_IS_PDI (0x0002) +#define PGM_FL_IS_JTAG (0x0004) + +static int jtagmkII_open(PROGRAMMER * pgm, char * port); + +static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p); +static int jtagmkII_chip_erase(PROGRAMMER * pgm, AVRPART * p); +static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value); +static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data); +static int jtagmkII_reset(PROGRAMMER * pgm, unsigned char flags); +static int jtagmkII_set_sck_period(PROGRAMMER * pgm, double v); +static int jtagmkII_setparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value); +static void jtagmkII_print_parms1(PROGRAMMER * pgm, const char * p); +static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes); + +// AVR32 +#define ERROR_SAB 0xFFFFFFFF + +static int jtagmkII_open32(PROGRAMMER * pgm, char * port); +static void jtagmkII_close32(PROGRAMMER * pgm); +static int jtagmkII_reset32(PROGRAMMER * pgm, unsigned short flags); +static int jtagmkII_initialize32(PROGRAMMER * pgm, AVRPART * p); +static int jtagmkII_chip_erase32(PROGRAMMER * pgm, AVRPART * p); +static unsigned long jtagmkII_read_SABaddr(PROGRAMMER * pgm, unsigned long addr, + unsigned int prefix); // ERROR_SAB illegal +static int jtagmkII_write_SABaddr(PROGRAMMER * pgm, unsigned long addr, + unsigned int prefix, unsigned long val); +static int jtagmkII_avr32_reset(PROGRAMMER * pgm, unsigned char val, + unsigned char ret1, unsigned char ret2); +static int jtagmkII_smc_init32(PROGRAMMER * pgm); +static int jtagmkII_paged_write32(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes); +static int jtagmkII_flash_lock32(PROGRAMMER * pgm, unsigned char lock, + unsigned int page); +static int jtagmkII_flash_erase32(PROGRAMMER * pgm, unsigned int page); +static int jtagmkII_flash_write_page32(PROGRAMMER * pgm, unsigned int page); +static int jtagmkII_flash_clear_pagebuffer32(PROGRAMMER * pgm); +static int jtagmkII_paged_load32(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes); + +void jtagmkII_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: jtagmkII_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +void jtagmkII_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + + +static unsigned long +b4_to_u32(unsigned char *b) +{ + unsigned long l; + l = b[0]; + l += (unsigned)b[1] << 8; + l += (unsigned)b[2] << 16; + l += (unsigned)b[3] << 24; + + return l; +} +static unsigned long +b4_to_u32r(unsigned char *b) +{ + unsigned long l; + l = b[3]; + l += (unsigned)b[2] << 8; + l += (unsigned)b[1] << 16; + l += (unsigned)b[0] << 24; + + return l; +} + +static void +u32_to_b4(unsigned char *b, unsigned long l) +{ + b[0] = l & 0xff; + b[1] = (l >> 8) & 0xff; + b[2] = (l >> 16) & 0xff; + b[3] = (l >> 24) & 0xff; +} +static void +u32_to_b4r(unsigned char *b, unsigned long l) +{ + b[3] = l & 0xff; + b[2] = (l >> 8) & 0xff; + b[1] = (l >> 16) & 0xff; + b[0] = (l >> 24) & 0xff; +} + +static unsigned short +b2_to_u16(unsigned char *b) +{ + unsigned short l; + l = b[0]; + l += (unsigned)b[1] << 8; + + return l; +} + +static void +u16_to_b2(unsigned char *b, unsigned short l) +{ + b[0] = l & 0xff; + b[1] = (l >> 8) & 0xff; +} + +static const char * +jtagmkII_get_rc(unsigned int rc) +{ + int i; + static char msg[50]; + + for (i = 0; i < sizeof jtagresults / sizeof jtagresults[0]; i++) + if (jtagresults[i].code == rc) + return jtagresults[i].descr; + + sprintf(msg, "Unknown JTAG ICE mkII result code 0x%02x", rc); + return msg; +} + + +static void jtagmkII_print_memory(unsigned char *b, size_t s) +{ + int i; + + if (s < 2) + return; + + for (i = 0; i < s - 1; i++) { + fprintf(stderr, "0x%02x ", b[i + 1]); + if (i % 16 == 15) + putc('\n', stderr); + else + putc(' ', stderr); + } + if (i % 16 != 0) + putc('\n', stderr); +} + +static void jtagmkII_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + int i; + + if (verbose >= 4) { + fprintf(stderr, "Raw message:\n"); + + for (i = 0; i < len; i++) { + fprintf(stderr, "0x%02x", data[i]); + if (i % 16 == 15) + putc('\n', stderr); + else + putchar(' '); + } + if (i % 16 != 0) + putc('\n', stderr); + } + + switch (data[0]) { + case RSP_OK: + fprintf(stderr, "OK\n"); + break; + + case RSP_FAILED: + fprintf(stderr, "FAILED\n"); + break; + + case RSP_ILLEGAL_BREAKPOINT: + fprintf(stderr, "Illegal breakpoint\n"); + break; + + case RSP_ILLEGAL_COMMAND: + fprintf(stderr, "Illegal command\n"); + break; + + case RSP_ILLEGAL_EMULATOR_MODE: + fprintf(stderr, "Illegal emulator mode"); + if (len > 1) + switch (data[1]) { + case EMULATOR_MODE_DEBUGWIRE: fprintf(stderr, ": DebugWire"); break; + case EMULATOR_MODE_JTAG: fprintf(stderr, ": JTAG"); break; + case EMULATOR_MODE_HV: fprintf(stderr, ": HVSP/PP"); break; + case EMULATOR_MODE_SPI: fprintf(stderr, ": SPI"); break; + case EMULATOR_MODE_JTAG_XMEGA: fprintf(stderr, ": JTAG/Xmega"); break; + } + putc('\n', stderr); + break; + + case RSP_ILLEGAL_JTAG_ID: + fprintf(stderr, "Illegal JTAG ID\n"); + break; + + case RSP_ILLEGAL_MCU_STATE: + fprintf(stderr, "Illegal MCU state"); + if (len > 1) + switch (data[1]) { + case STOPPED: fprintf(stderr, ": Stopped"); break; + case RUNNING: fprintf(stderr, ": Running"); break; + case PROGRAMMING: fprintf(stderr, ": Programming"); break; + } + putc('\n', stderr); + break; + + case RSP_ILLEGAL_MEMORY_TYPE: + fprintf(stderr, "Illegal memory type\n"); + break; + + case RSP_ILLEGAL_MEMORY_RANGE: + fprintf(stderr, "Illegal memory range\n"); + break; + + case RSP_ILLEGAL_PARAMETER: + fprintf(stderr, "Illegal parameter\n"); + break; + + case RSP_ILLEGAL_POWER_STATE: + fprintf(stderr, "Illegal power state\n"); + break; + + case RSP_ILLEGAL_VALUE: + fprintf(stderr, "Illegal value\n"); + break; + + case RSP_NO_TARGET_POWER: + fprintf(stderr, "No target power\n"); + break; + + case RSP_SIGN_ON: + fprintf(stderr, "Sign-on succeeded\n"); + /* Sign-on data will be printed below anyway. */ + break; + + case RSP_MEMORY: + fprintf(stderr, "memory contents:\n"); + jtagmkII_print_memory(data, len); + break; + + case RSP_PARAMETER: + fprintf(stderr, "parameter values:\n"); + jtagmkII_print_memory(data, len); + break; + + case RSP_SPI_DATA: + fprintf(stderr, "SPI data returned:\n"); + for (i = 1; i < len; i++) + fprintf(stderr, "0x%02x ", data[i]); + putc('\n', stderr); + break; + + case EVT_BREAK: + fprintf(stderr, "BREAK event"); + if (len >= 6) { + fprintf(stderr, ", PC = 0x%lx, reason ", b4_to_u32(data + 1)); + switch (data[5]) { + case 0x00: + fprintf(stderr, "unspecified"); + break; + case 0x01: + fprintf(stderr, "program break"); + break; + case 0x02: + fprintf(stderr, "data break PDSB"); + break; + case 0x03: + fprintf(stderr, "data break PDMSB"); + break; + default: + fprintf(stderr, "unknown: 0x%02x", data[5]); + } + } + putc('\n', stderr); + break; + + default: + fprintf(stderr, "unknown message 0x%02x\n", data[0]); + } + + putc('\n', stderr); +} + + +int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + unsigned char *buf; + + if (verbose >= 3) + fprintf(stderr, "\n%s: jtagmkII_send(): sending %lu bytes\n", + progname, (unsigned long)len); + + if ((buf = malloc(len + 10)) == NULL) + { + fprintf(stderr, "%s: jtagmkII_send(): out of memory", + progname); + return -1; + } + + buf[0] = MESSAGE_START; + u16_to_b2(buf + 1, PDATA(pgm)->command_sequence); + u32_to_b4(buf + 3, len); + buf[7] = TOKEN; + memcpy(buf + 8, data, len); + + crcappend(buf, len + 8); + + if (serial_send(&pgm->fd, buf, len + 10) != 0) { + fprintf(stderr, + "%s: jtagmkII_send(): failed to send command to serial port\n", + progname); + exit(1); + } + + free(buf); + + return 0; +} + + +static int jtagmkII_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(&pgm->fd, display); +} + + +/* + * Receive one frame, return it in *msg. Received sequence number is + * returned in seqno. Any valid frame will be returned, regardless + * whether it matches the expected sequence number, including event + * notification frames (seqno == 0xffff). + * + * Caller must eventually free the buffer. + */ +static int jtagmkII_recv_frame(PROGRAMMER * pgm, unsigned char **msg, + unsigned short * seqno) { + enum states { sSTART, + /* NB: do NOT change the sequence of the following: */ + sSEQNUM1, sSEQNUM2, + sSIZE1, sSIZE2, sSIZE3, sSIZE4, + sTOKEN, + sDATA, + sCSUM1, sCSUM2, + /* end NB */ + sDONE + } state = sSTART; + unsigned long msglen = 0, l = 0; + int headeridx = 0; + int timeout = 0; + int ignorpkt = 0; + int rv; + unsigned char c, *buf = NULL, header[8]; + unsigned short r_seqno = 0; + unsigned short checksum = 0; + + struct timeval tv; + double timeoutval = 100; /* seconds */ + double tstart, tnow; + + if (verbose >= 4) + fprintf(stderr, "%s: jtagmkII_recv():\n", progname); + + gettimeofday(&tv, NULL); + tstart = tv.tv_sec; + + while ( (state != sDONE ) && (!timeout) ) { + if (state == sDATA) { + rv = 0; + if (ignorpkt) { + /* skip packet's contents */ + for(l = 0; l < msglen; l++) + rv += serial_recv(&pgm->fd, &c, 1); + } else { + rv += serial_recv(&pgm->fd, buf + 8, msglen); + } + if (rv != 0) { + timedout: + /* timeout in receive */ + if (verbose > 1) + fprintf(stderr, + "%s: jtagmkII_recv(): Timeout receiving packet\n", + progname); + free(buf); + return -1; + } + } else { + if (serial_recv(&pgm->fd, &c, 1) != 0) + goto timedout; + } + checksum ^= c; + + if (state < sDATA) + header[headeridx++] = c; + + switch (state) { + case sSTART: + if (c == MESSAGE_START) { + state = sSEQNUM1; + } else { + headeridx = 0; + } + break; + case sSEQNUM1: + case sSEQNUM2: + r_seqno >>= 8; + r_seqno |= ((unsigned)c << 8); + state++; + break; + case sSIZE1: + case sSIZE2: + case sSIZE3: + case sSIZE4: + msglen >>= 8; + msglen |= ((unsigned)c << 24); + state++; + break; + case sTOKEN: + if (c == TOKEN) { + state = sDATA; + if (msglen > MAX_MESSAGE) { + fprintf(stderr, + "%s: jtagmkII_recv(): msglen %lu exceeds max message " + "size %u, ignoring message\n", + progname, msglen, MAX_MESSAGE); + state = sSTART; + headeridx = 0; + } else if ((buf = malloc(msglen + 10)) == NULL) { + fprintf(stderr, "%s: jtagmkII_recv(): out of memory\n", + progname); + ignorpkt++; + } else { + memcpy(buf, header, 8); + } + } else { + state = sSTART; + headeridx = 0; + } + break; + case sDATA: + /* The entire payload has been read above. */ + l = msglen + 8; + state = sCSUM1; + break; + case sCSUM1: + case sCSUM2: + buf[l++] = c; + if (state == sCSUM2) { + if (crcverify(buf, msglen + 10)) { + if (verbose >= 9) + fprintf(stderr, "%s: jtagmkII_recv(): CRC OK", + progname); + state = sDONE; + } else { + fprintf(stderr, "%s: jtagmkII_recv(): checksum error\n", + progname); + free(buf); + return -4; + } + } else + state++; + break; + default: + fprintf(stderr, "%s: jtagmkII_recv(): unknown state\n", + progname); + free(buf); + return -5; + } + + gettimeofday(&tv, NULL); + tnow = tv.tv_sec; + if (tnow - tstart > timeoutval) { + fprintf(stderr, "%s: jtagmkII_recv_frame(): timeout\n", + progname); + return -1; + } + + } + if (verbose >= 3) + fprintf(stderr, "\n"); + + *seqno = r_seqno; + *msg = buf; + + return msglen; +} + +int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) { + unsigned short r_seqno; + int rv; + + for (;;) { + if ((rv = jtagmkII_recv_frame(pgm, msg, &r_seqno)) <= 0) + return rv; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_recv(): " + "Got message seqno %d (command_sequence == %d)\n", + progname, r_seqno, PDATA(pgm)->command_sequence); + if (r_seqno == PDATA(pgm)->command_sequence) { + if (++(PDATA(pgm)->command_sequence) == 0xffff) + PDATA(pgm)->command_sequence = 0; + /* + * We move the payload to the beginning of the buffer, to make + * the job easier for the caller. We have to return the + * original pointer though, as the caller must free() it. + */ + memmove(*msg, *msg + 8, rv); + + if (verbose == 4) + { + int i = rv; + unsigned char *p = *msg; + fprintf(stderr, "%s: Recv: ", progname); + + while (i) { + unsigned char c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + i--; + } + fprintf(stderr, "\n"); + } + return rv; + } + if (r_seqno == 0xffff) { + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_recv(): got asynchronous event\n", + progname); + } else { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_recv(): " + "got wrong sequence number, %u != %u\n", + progname, r_seqno, PDATA(pgm)->command_sequence); + } + free(*msg); + } +} + + +int jtagmkII_getsync(PROGRAMMER * pgm, int mode) { + int tries; +#define MAXTRIES 33 + unsigned char buf[3], *resp, c = 0xff; + int status; + unsigned int fwver, hwver; + int is_dragon; + + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_getsync()\n", progname); + + if (strncmp(pgm->type, "JTAG", strlen("JTAG")) == 0) { + is_dragon = 0; + } else if (strncmp(pgm->type, "DRAGON", strlen("DRAGON")) == 0) { + is_dragon = 1; + } else { + fprintf(stderr, + "%s: Programmer is neither JTAG ICE mkII nor AVR Dragon\n", + progname); + return -1; + } + for (tries = 0; tries < MAXTRIES; tries++) { + + /* Get the sign-on information. */ + buf[0] = CMND_GET_SIGN_ON; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_getsync(): Sending sign-on command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + fprintf(stderr, "%s: jtagmkII_getsync(): sign-on command: " + "status %d\n", + progname, status); + } else if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + + if (status > 0) { + if ((c = resp[0]) == RSP_SIGN_ON) { + fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7]; + hwver = (unsigned)resp[9]; + memcpy(PDATA(pgm)->serno, resp + 10, 6); + if (verbose >= 1 && status > 17) { + fprintf(stderr, "JTAG ICE mkII sign-on message:\n"); + fprintf(stderr, "Communications protocol version: %u\n", + (unsigned)resp[1]); + fprintf(stderr, "M_MCU:\n"); + fprintf(stderr, " boot-loader FW version: %u\n", + (unsigned)resp[2]); + fprintf(stderr, " firmware version: %u.%02u\n", + (unsigned)resp[4], (unsigned)resp[3]); + fprintf(stderr, " hardware version: %u\n", + (unsigned)resp[5]); + fprintf(stderr, "S_MCU:\n"); + fprintf(stderr, " boot-loader FW version: %u\n", + (unsigned)resp[6]); + fprintf(stderr, " firmware version: %u.%02u\n", + (unsigned)resp[8], (unsigned)resp[7]); + fprintf(stderr, " hardware version: %u\n", + (unsigned)resp[9]); + fprintf(stderr, "Serial number: " + "%02x:%02x:%02x:%02x:%02x:%02x\n", + PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]); + resp[status - 1] = '\0'; + fprintf(stderr, "Device ID: %s\n", + resp + 16); + } + break; + } + free(resp); + } + } + if (tries >= MAXTRIES) { + if (status <= 0) + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + else + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "bad response to sign-on command: %s\n", + progname, jtagmkII_get_rc(c)); + return -1; + } + + PDATA(pgm)->device_descriptor_length = sizeof(struct device_descriptor); + /* + * There's no official documentation from Atmel about what firmware + * revision matches what device descriptor length. The algorithm + * below has been found empirically. + */ +#define FWVER(maj, min) ((maj << 8) | (min)) + if (!is_dragon && fwver < FWVER(3, 16)) { + PDATA(pgm)->device_descriptor_length -= 2; + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "S_MCU firmware version might be too old to work correctly\n", + progname); + } else if (!is_dragon && fwver < FWVER(4, 0)) { + PDATA(pgm)->device_descriptor_length -= 2; + } + if (verbose >= 2 && mode != EMULATOR_MODE_SPI) + fprintf(stderr, + "%s: jtagmkII_getsync(): Using a %u-byte device descriptor\n", + progname, (unsigned)PDATA(pgm)->device_descriptor_length); + if (mode == EMULATOR_MODE_SPI) { + PDATA(pgm)->device_descriptor_length = 0; + if (!is_dragon && fwver < FWVER(4, 14)) { + fprintf(stderr, + "%s: jtagmkII_getsync(): ISP functionality requires firmware " + "version >= 4.14\n", + progname); + return -1; + } + } + if (mode == EMULATOR_MODE_PDI || mode == EMULATOR_MODE_JTAG_XMEGA) { + if (!is_dragon && mode == EMULATOR_MODE_PDI && hwver < 1) { + fprintf(stderr, + "%s: jtagmkII_getsync(): Xmega PDI support requires hardware " + "revision >= 1\n", + progname); + return -1; + } + if (!is_dragon && fwver < FWVER(5, 37)) { + fprintf(stderr, + "%s: jtagmkII_getsync(): Xmega support requires firmware " + "version >= 5.37\n", + progname); + return -1; + } + if (is_dragon && fwver < FWVER(6, 11)) { + fprintf(stderr, + "%s: jtagmkII_getsync(): Xmega support requires firmware " + "version >= 6.11\n", + progname); + return -1; + } + } +#undef FWVER + + if(mode < 0) return 0; // for AVR32 + + /* Turn the ICE into JTAG or ISP mode as requested. */ + buf[0] = mode; + if (jtagmkII_setparm(pgm, PAR_EMULATOR_MODE, buf) < 0) { + if (mode == EMULATOR_MODE_SPI) { + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "ISP activation failed, trying debugWire\n", + progname); + buf[0] = EMULATOR_MODE_DEBUGWIRE; + if (jtagmkII_setparm(pgm, PAR_EMULATOR_MODE, buf) < 0) + return -1; + else { + /* + * We are supposed to send a CMND_RESET with the + * MONCOM_DISABLE flag set right now, and then + * restart from scratch. + * + * As this will make the ICE sign off from USB, so + * we risk losing our USB connection, it's easier + * to instruct the user to restart AVRDUDE rather + * than trying to cope with all this inside the + * program. + */ + (void)jtagmkII_reset(pgm, 0x04); + fprintf(stderr, + "%s: Target prepared for ISP, signed off.\n" + "%s: Please restart %s without power-cycling the target.\n", + progname, progname, progname); + return JTAGII_GETSYNC_FAIL_GRACEFUL; + } + } else { + return -1; + } + } + + /* GET SYNC forces the target into STOPPED mode */ + buf[0] = CMND_GET_SYNC; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_getsync(): Sending get sync command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "bad response to set parameter command: %s\n", + progname, jtagmkII_get_rc(c)); + return -1; + } + + return 0; +} + +/* + * issue the 'chip erase' command to the AVR device + */ +static int jtagmkII_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + int status, len; + unsigned char buf[6], *resp, c; + + if (p->flags & AVRPART_HAS_PDI) { + buf[0] = CMND_XMEGA_ERASE; + buf[1] = XMEGA_ERASE_CHIP; + memset(buf + 2, 0, 4); /* address of area to be erased */ + len = 6; + } else { + buf[0] = CMND_CHIP_ERASE; + len = 1; + } + if (verbose >= 2) + fprintf(stderr, + "%s: jtagmkII_chip_erase(): Sending %schip erase command: ", + progname, + (p->flags & AVRPART_HAS_PDI)? "Xmega ": ""); + jtagmkII_send(pgm, buf, len); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_chip_erase(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_chip_erase(): " + "bad response to chip erase command: %s\n", + progname, jtagmkII_get_rc(c)); + return -1; + } + + if (!(p->flags & AVRPART_HAS_PDI)) + pgm->initialize(pgm, p); + + return 0; +} + +/* + * There is no chip erase functionality in debugWire mode. + */ +static int jtagmkII_chip_erase_dw(PROGRAMMER * pgm, AVRPART * p) +{ + + fprintf(stderr, "%s: Chip erase not supported in debugWire mode\n", + progname); + + return 0; +} + +static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) +{ + int status; + unsigned char *resp, c; + LNODEID ln; + AVRMEM * m; + struct { + unsigned char cmd; + struct device_descriptor dd; + } sendbuf; + + memset(&sendbuf, 0, sizeof sendbuf); + sendbuf.cmd = CMND_SET_DEVICE_DESCRIPTOR; + sendbuf.dd.ucSPMCRAddress = p->spmcr; + sendbuf.dd.ucRAMPZAddress = p->rampz; + sendbuf.dd.ucIDRAddress = p->idr; + u16_to_b2(sendbuf.dd.EECRAddress, p->eecr); + sendbuf.dd.ucAllowFullPageBitstream = + (p->flags & AVRPART_ALLOWFULLPAGEBITSTREAM) != 0; + sendbuf.dd.EnablePageProgramming = + (p->flags & AVRPART_ENABLEPAGEPROGRAMMING) != 0; + for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { + m = ldata(ln); + if (strcmp(m->desc, "flash") == 0) { + PDATA(pgm)->flash_pagesize = m->page_size; + u32_to_b4(sendbuf.dd.ulFlashSize, m->size); + u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize); + u16_to_b2(sendbuf.dd.uiFlashpages, m->size / PDATA(pgm)->flash_pagesize); + if (p->flags & AVRPART_HAS_DW) { + memcpy(sendbuf.dd.ucFlashInst, p->flash_instr, FLASH_INSTR_SIZE); + memcpy(sendbuf.dd.ucEepromInst, p->eeprom_instr, EEPROM_INSTR_SIZE); + } + } else if (strcmp(m->desc, "eeprom") == 0) { + sendbuf.dd.ucEepromPageSize = PDATA(pgm)->eeprom_pagesize = m->page_size; + } + } + sendbuf.dd.ucCacheType = + (p->flags & AVRPART_HAS_PDI)? 0x02 /* ATxmega */: 0x00; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_set_devdescr(): " + "Sending set device descriptor command: ", + progname); + jtagmkII_send(pgm, (unsigned char *)&sendbuf, + PDATA(pgm)->device_descriptor_length + sizeof(unsigned char)); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_set_devdescr(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_set_devdescr(): " + "bad response to set device descriptor command: %s\n", + progname, jtagmkII_get_rc(c)); + } +} + +/* + * Reset the target. + */ +static int jtagmkII_reset(PROGRAMMER * pgm, unsigned char flags) +{ + int status; + unsigned char buf[2], *resp, c; + + /* + * In debugWire mode, don't reset. Do a forced stop, and tell the + * ICE to stop any timers, too. + */ + if (pgm->flag & PGM_FL_IS_DW) { + unsigned char parm[] = { 0 }; + + (void)jtagmkII_setparm(pgm, PAR_TIMERS_RUNNING, parm); + } + + buf[0] = (pgm->flag & PGM_FL_IS_DW)? CMND_FORCED_STOP: CMND_RESET; + buf[1] = (pgm->flag & PGM_FL_IS_DW)? 1: flags; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_reset(): Sending %s command: ", + progname, (pgm->flag & PGM_FL_IS_DW)? "stop": "reset"); + jtagmkII_send(pgm, buf, 2); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_reset(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_reset(): " + "bad response to reset command: %s\n", + progname, jtagmkII_get_rc(c)); + return -1; + } + + return 0; +} + +static int jtagmkII_program_enable_dummy(PROGRAMMER * pgm, AVRPART * p) +{ + return 0; +} + +static int jtagmkII_program_enable(PROGRAMMER * pgm) +{ + int status; + unsigned char buf[1], *resp, c; + int use_ext_reset; + + if (PDATA(pgm)->prog_enabled) + return 0; + + for (use_ext_reset = 0; use_ext_reset <= 1; use_ext_reset++) { + buf[0] = CMND_ENTER_PROGMODE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_program_enable(): " + "Sending enter progmode command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_program_enable(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_program_enable(): " + "bad response to enter progmode command: %s\n", + progname, jtagmkII_get_rc(c)); + if (c == RSP_ILLEGAL_JTAG_ID) { + if (use_ext_reset == 0) { + unsigned char parm[] = { 1}; + if (verbose > 0) + fprintf(stderr, + "%s: retrying with external reset applied\n", + progname); + + (void)jtagmkII_setparm(pgm, PAR_EXTERNAL_RESET, parm); + continue; + } + + fprintf(stderr, "%s: JTAGEN fuse disabled?\n", progname); + return -1; + } + } + } + + PDATA(pgm)->prog_enabled = 1; + return 0; +} + +static int jtagmkII_program_disable(PROGRAMMER * pgm) +{ + int status; + unsigned char buf[1], *resp, c; + + if (!PDATA(pgm)->prog_enabled) + return 0; + + buf[0] = CMND_LEAVE_PROGMODE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_program_disable(): " + "Sending leave progmode command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_program_disable(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_program_disable(): " + "bad response to leave progmode command: %s\n", + progname, jtagmkII_get_rc(c)); + return -1; + } + + PDATA(pgm)->prog_enabled = 0; + (void)jtagmkII_reset(pgm, 0x01); + + return 0; +} + +static unsigned char jtagmkII_get_baud(long baud) +{ + static struct { + long baud; + unsigned char val; + } baudtab[] = { + { 2400L, PAR_BAUD_2400 }, + { 4800L, PAR_BAUD_4800 }, + { 9600L, PAR_BAUD_9600 }, + { 19200L, PAR_BAUD_19200 }, + { 38400L, PAR_BAUD_38400 }, + { 57600L, PAR_BAUD_57600 }, + { 115200L, PAR_BAUD_115200 }, + { 14400L, PAR_BAUD_14400 }, + }; + int i; + + for (i = 0; i < sizeof baudtab / sizeof baudtab[0]; i++) + if (baud == baudtab[i].baud) + return baudtab[i].val; + + return 0; +} + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + AVRMEM hfuse; + unsigned char b; + int ok; + const char *ifname; + + ok = 0; + if (pgm->flag & PGM_FL_IS_DW) { + ifname = "debugWire"; + if (p->flags & AVRPART_HAS_DW) + ok = 1; + } else if (pgm->flag & PGM_FL_IS_PDI) { + ifname = "PDI"; + if (p->flags & AVRPART_HAS_PDI) + ok = 1; + } else { + ifname = "JTAG"; + if (p->flags & AVRPART_HAS_JTAG) + ok = 1; + } + + if (!ok) { + fprintf(stderr, "%s: jtagmkII_initialize(): part %s has no %s interface\n", + progname, p->desc, ifname); + return -1; + } + + if ((serdev->flags & SERDEV_FL_CANSETSPEED) && pgm->baudrate && pgm->baudrate != 19200) { + if ((b = jtagmkII_get_baud(pgm->baudrate)) == 0) { + fprintf(stderr, "%s: jtagmkII_initialize(): unsupported baudrate %d\n", + progname, pgm->baudrate); + } else { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_initialize(): " + "trying to set baudrate to %d\n", + progname, pgm->baudrate); + if (jtagmkII_setparm(pgm, PAR_BAUD_RATE, &b) == 0) + serial_setspeed(&pgm->fd, pgm->baudrate); + } + } + if ((pgm->flag & PGM_FL_IS_JTAG) && pgm->bitclock != 0.0) { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_initialize(): " + "trying to set JTAG clock period to %.1f us\n", + progname, pgm->bitclock); + if (jtagmkII_set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + if ((pgm->flag & PGM_FL_IS_JTAG) && + jtagmkII_setparm(pgm, PAR_DAISY_CHAIN_INFO, PDATA(pgm)->jtagchain) < 0) { + fprintf(stderr, "%s: jtagmkII_initialize(): Failed to setup JTAG chain\n", + progname); + return -1; + } + + /* + * Must set the device descriptor before entering programming mode. + */ + jtagmkII_set_devdescr(pgm, p); + + /* + * If this is an ATxmega device in JTAG mode, change the emulator + * mode from JTAG to JTAG_XMEGA. + */ + if ((pgm->flag & PGM_FL_IS_JTAG) && + (p->flags & AVRPART_HAS_PDI)) { + if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG_XMEGA) < 0) + return -1; + } + + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n", + progname); + return -1; + } + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n", + progname); + free(PDATA(pgm)->flash_pagecache); + return -1; + } + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + + if (jtagmkII_reset(pgm, 0x01) < 0) + return -1; + + if ((pgm->flag & PGM_FL_IS_JTAG) && !(p->flags & AVRPART_HAS_PDI)) { + strcpy(hfuse.desc, "hfuse"); + if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) + return -1; + if ((b & OCDEN) != 0) + fprintf(stderr, + "%s: jtagmkII_initialize(): warning: OCDEN fuse not programmed, " + "single-byte EEPROM updates not possible\n", + progname); + } + + return 0; +} + +static void jtagmkII_disable(PROGRAMMER * pgm) +{ + + free(PDATA(pgm)->flash_pagecache); + PDATA(pgm)->flash_pagecache = NULL; + free(PDATA(pgm)->eeprom_pagecache); + PDATA(pgm)->eeprom_pagecache = NULL; + + /* + * jtagmkII_program_disable() doesn't do anything if the + * device is currently not in programming mode, so just + * call it unconditionally here. + */ + (void)jtagmkII_program_disable(pgm); +} + +static void jtagmkII_enable(PROGRAMMER * pgm) +{ + return; +} + +static int jtagmkII_parseextparms(PROGRAMMER * pgm, LISTID extparms) +{ + LNODEID ln; + const char *extended_param; + int rv = 0; + + for (ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if (strncmp(extended_param, "jtagchain=", strlen("jtagchain=")) == 0) { + unsigned int ub, ua, bb, ba; + if (sscanf(extended_param, "jtagchain=%u,%u,%u,%u", &ub, &ua, &bb, &ba) + != 4) { + fprintf(stderr, + "%s: jtagmkII_parseextparms(): invalid JTAG chain '%s'\n", + progname, extended_param); + rv = -1; + continue; + } + if (verbose >= 2) { + fprintf(stderr, + "%s: jtagmkII_parseextparms(): JTAG chain parsed as:\n" + "%s %u units before, %u units after, %u bits before, %u bits after\n", + progname, + progbuf, ub, ua, bb, ba); + } + PDATA(pgm)->jtagchain[0] = ub; + PDATA(pgm)->jtagchain[1] = ua; + PDATA(pgm)->jtagchain[2] = bb; + PDATA(pgm)->jtagchain[3] = ba; + + continue; + } + + fprintf(stderr, + "%s: jtagmkII_parseextparms(): invalid extended parameter '%s'\n", + progname, extended_param); + rv = -1; + } + + return rv; +} + + +static int jtagmkII_open(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_open()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_JTAGICEMKII; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) + return -1; + + return 0; +} + +static int jtagmkII_open_dw(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_open_dw()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_JTAGICEMKII; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) + return -1; + + return 0; +} + +static int jtagmkII_open_pdi(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_open_pdi()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_JTAGICEMKII; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) + return -1; + + return 0; +} + + +static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_dragon_open()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_AVRDRAGON; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) + return -1; + + return 0; +} + + +static int jtagmkII_dragon_open_dw(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_dragon_open_dw()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_AVRDRAGON; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) + return -1; + + return 0; +} + + +static int jtagmkII_dragon_open_pdi(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_dragon_open_pdi()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_AVRDRAGON; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) + return -1; + + return 0; +} + + +void jtagmkII_close(PROGRAMMER * pgm) +{ + int status; + unsigned char buf[1], *resp, c; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_close()\n", progname); + + if (PDATA(pgm)->device_descriptor_length) { + /* When in JTAG mode, restart target. */ + buf[0] = CMND_GO; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_close(): Sending GO command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_close(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + } else { + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_close(): " + "bad response to GO command: %s\n", + progname, jtagmkII_get_rc(c)); + } + } + } + + buf[0] = CMND_SIGN_OFF; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_close(): Sending sign-off command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_close(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_close(): " + "bad response to sign-off command: %s\n", + progname, jtagmkII_get_rc(c)); + } + + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + +static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int addr, block_size; + unsigned char *cmd; + unsigned char *resp; + unsigned char par[4]; + int status, tries; + long otimeout = serial_recv_timeout; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_paged_write(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0) + return -1; + + if (page_size == 0) page_size = 256; + + if ((cmd = malloc(page_size + 10)) == NULL) { + fprintf(stderr, "%s: jtagmkII_paged_write(): Out of memory\n", + progname); + return -1; + } + if ( p->flags & AVRPART_HAS_PDI ) + { + u32_to_b4( par, m->offset ); + (void) jtagmkII_setparm( pgm, PAR_PDI_OFFSET_START, par ); + u32_to_b4( par, m->offset + m->size ); + (void) jtagmkII_setparm( pgm, PAR_PDI_OFFSET_END, par ); + } + + cmd[0] = CMND_WRITE_MEMORY; + cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; + if (strcmp(m->desc, "flash") == 0) { + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->flash_pagesize; + } else if (strcmp(m->desc, "eeprom") == 0) { + if (pgm->flag & PGM_FL_IS_DW) { + /* + * jtagmkII_paged_write() to EEPROM attempted while in + * DW mode. Use jtagmkII_write_byte() instead. + */ + for (addr = 0; addr < n_bytes; addr++) { + status = jtagmkII_write_byte(pgm, p, m, addr, m->buf[addr]); + report_progress(addr, n_bytes, NULL); + if (status < 0) { + free(cmd); + return -1; + } + } + free(cmd); + return n_bytes; + } + cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->eeprom_pagesize; + } + serial_recv_timeout = 100; + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_paged_write(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + u32_to_b4(cmd + 2, page_size); + u32_to_b4(cmd + 6, addr+m->offset ); + + /* + * The JTAG ICE will refuse to write anything but a full page, at + * least for the flash ROM. If a partial page has been requested, + * set the remainder to 0xff. (Maybe we should rather read back + * the existing contents instead before? Doesn't matter much, as + * bits cannot be written to 1 anyway.) + */ + memset(cmd + 10, 0xff, page_size); + memcpy(cmd + 10, m->buf + addr, block_size); + + tries = 0; + + retry: + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_paged_write(): " + "Sending write memory command: ", + progname); + jtagmkII_send(pgm, cmd, page_size + 10); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + if (verbose >= 1) + fprintf(stderr, + "%s: jtagmkII_paged_write(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + if (tries++ < 4) { + serial_recv_timeout *= 2; + goto retry; + } + fprintf(stderr, + "%s: jtagmkII_paged_write(): fatal timeout/" + "error communicating with programmer (status %d)\n", + progname, status); + free(cmd); + serial_recv_timeout = otimeout; + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_paged_write(): " + "bad response to write memory command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + free(resp); + free(cmd); + serial_recv_timeout = otimeout; + return -1; + } + free(resp); + } + + free(cmd); + serial_recv_timeout = otimeout; + + return n_bytes; +} + +static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int addr, block_size; + unsigned char cmd[10]; + unsigned char *resp; + int status, tries; + long otimeout = serial_recv_timeout; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_paged_load(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0) + return -1; + + page_size = m->readsize; + + cmd[0] = CMND_READ_MEMORY; + cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; + if (strcmp(m->desc, "eeprom") == 0) { + cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; + if (pgm->flag & PGM_FL_IS_DW) + return -1; + } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) { + cmd[1] = MTYPE_PRODSIG; + } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { + cmd[1] = MTYPE_USERSIG; + } + serial_recv_timeout = 100; + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_paged_load(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + u32_to_b4(cmd + 2, block_size); + u32_to_b4(cmd + 6, addr+m->offset ); + + tries = 0; + + retry: + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_paged_load(): Sending read memory command: ", + progname); + jtagmkII_send(pgm, cmd, 10); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + if (verbose >= 1) + fprintf(stderr, + "%s: jtagmkII_paged_load(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + if (tries++ < 4) { + serial_recv_timeout *= 2; + goto retry; + } + fprintf(stderr, + "%s: jtagmkII_paged_load(): fatal timeout/" + "error communicating with programmer (status %d)\n", + progname, status); + serial_recv_timeout = otimeout; + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != RSP_MEMORY) { + fprintf(stderr, + "%s: jtagmkII_paged_load(): " + "bad response to read memory command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + free(resp); + serial_recv_timeout = otimeout; + return -1; + } + memcpy(m->buf + addr, resp + 1, status-1); + free(resp); + } + serial_recv_timeout = otimeout; + + return n_bytes; +} + +static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + unsigned char cmd[10]; + unsigned char *resp = NULL, *cache_ptr = NULL; + int status, tries, unsupp; + unsigned long paddr = 0UL, *paddr_ptr = NULL; + unsigned int pagesize = 0; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_read_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0) + return -1; + + cmd[0] = CMND_READ_MEMORY; + unsupp = 0; + + addr += mem->offset; + cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; + if (strcmp(mem->desc, "flash") == 0) { + pagesize = mem->page_size; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; + } else if (strcmp(mem->desc, "eeprom") == 0) { + if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) ) { + /* debugWire cannot use page access for EEPROM */ + cmd[1] = MTYPE_EEPROM; + } else { + cmd[1] = MTYPE_EEPROM_PAGE; + pagesize = mem->page_size; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; + } + } else if (strcmp(mem->desc, "lfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 0; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "hfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 1; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 2; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "lock") == 0) { + cmd[1] = MTYPE_LOCK_BITS; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { + cmd[1] = MTYPE_FUSE_BITS; + } else if (strcmp(mem->desc, "usersig") == 0) { + cmd[1] = MTYPE_USERSIG; + } else if (strcmp(mem->desc, "prodsig") == 0) { + cmd[1] = MTYPE_PRODSIG; + } else if (strcmp(mem->desc, "calibration") == 0) { + cmd[1] = MTYPE_OSCCAL_BYTE; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "signature") == 0) { + cmd[1] = MTYPE_SIGN_JTAG; + + if (pgm->flag & PGM_FL_IS_DW) { + /* + * In debugWire mode, there is no accessible memory area to read + * the signature from, but the essential two bytes can be read + * as a parameter from the ICE. + */ + unsigned char parm[4]; + + switch (addr) { + case 0: + *value = 0x1E; /* Atmel vendor ID */ + break; + + case 1: + case 2: + if (jtagmkII_getparm(pgm, PAR_TARGET_SIGNATURE, parm) < 0) + return -1; + *value = parm[2 - addr]; + break; + + default: + fprintf(stderr, "%s: illegal address %lu for signature memory\n", + progname, addr); + return -1; + } + return 0; + } + + } + + /* + * If the respective memory area is not supported under debugWire, + * leave here. + */ + if (unsupp) { + *value = 42; + return -1; + } + + /* + * To improve the read speed, we used paged reads for flash and + * EEPROM, and cache the results in a page cache. + * + * Page cache validation is based on "{flash,eeprom}_pageaddr" + * (holding the base address of the most recent cache fill + * operation). This variable is set to (unsigned long)-1L when the + * cache needs to be invalidated. + */ + if (pagesize && paddr == *paddr_ptr) { + *value = cache_ptr[addr & (pagesize - 1)]; + return 0; + } + + if (pagesize) { + u32_to_b4(cmd + 2, pagesize); + u32_to_b4(cmd + 6, paddr); + } else { + u32_to_b4(cmd + 2, 1); + u32_to_b4(cmd + 6, addr); + } + + tries = 0; + retry: + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_read_byte(): Sending read memory command: ", + progname); + jtagmkII_send(pgm, cmd, 10); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + if (verbose >= 1) + fprintf(stderr, + "%s: jtagmkII_read_byte(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + if (tries++ < 3) + goto retry; + fprintf(stderr, + "%s: jtagmkII_read_byte(): " + "fatal timeout/error communicating with programmer (status %d)\n", + progname, status); + if (status < 0) + resp = 0; + goto fail; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != RSP_MEMORY) { + fprintf(stderr, + "%s: jtagmkII_read_byte(): " + "bad response to read memory command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + goto fail; + } + + if (pagesize) { + *paddr_ptr = paddr; + memcpy(cache_ptr, resp + 1, pagesize); + *value = cache_ptr[addr & (pagesize - 1)]; + } else + *value = resp[1]; + + free(resp); + return 0; + +fail: + free(resp); + return -1; +} + +static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + unsigned char cmd[11]; + unsigned char *resp = NULL, writedata; + int status, tries, need_progmode = 1, unsupp = 0; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_write_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + addr += mem->offset; + + writedata = data; + cmd[0] = CMND_WRITE_MEMORY; + cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_SPM; + if (strcmp(mem->desc, "flash") == 0) { + need_progmode = 0; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM; + need_progmode = 0; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + } else if (strcmp(mem->desc, "lfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 0; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "hfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 1; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 2; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { + cmd[1] = MTYPE_FUSE_BITS; + } else if (strcmp(mem->desc, "usersig") == 0) { + cmd[1] = MTYPE_USERSIG; + } else if (strcmp(mem->desc, "prodsig") == 0) { + cmd[1] = MTYPE_PRODSIG; + } else if (strcmp(mem->desc, "lock") == 0) { + cmd[1] = MTYPE_LOCK_BITS; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "calibration") == 0) { + cmd[1] = MTYPE_OSCCAL_BYTE; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } else if (strcmp(mem->desc, "signature") == 0) { + cmd[1] = MTYPE_SIGN_JTAG; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; + } + + if (unsupp) + return -1; + + if (need_progmode) { + if (jtagmkII_program_enable(pgm) < 0) + return -1; + } else { + if (jtagmkII_program_disable(pgm) < 0) + return -1; + } + + u32_to_b4(cmd + 2, 1); + u32_to_b4(cmd + 6, addr); + cmd[10] = writedata; + + tries = 0; + retry: + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_write_byte(): Sending write memory command: ", + progname); + jtagmkII_send(pgm, cmd, 11); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + if (verbose > 1) + fprintf(stderr, + "%s: jtagmkII_write_byte(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + if (tries++ < 3) + goto retry; + fprintf(stderr, + "%s: jtagmkII_write_byte(): " + "fatal timeout/error communicating with programmer (status %d)\n", + progname, status); + goto fail; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_write_byte(): " + "bad response to write memory command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + goto fail; + } + + free(resp); + return 0; + +fail: + free(resp); + return -1; +} + + +/* + * Set the JTAG clock. The actual frequency is quite a bit of + * guesswork, based on the values claimed by AVR Studio. Inside the + * JTAG ICE, the value is the delay count of a delay loop between the + * JTAG clock edges. A count of 0 bypasses the delay loop. + * + * As the STK500 expresses it as a period length (and we actualy do + * program a period length as well), we rather call it by that name. + */ +static int jtagmkII_set_sck_period(PROGRAMMER * pgm, double v) +{ + unsigned char dur; + + v = 1 / v; /* convert to frequency */ + if (v >= 6.4e6) + dur = 0; + else if (v >= 2.8e6) + dur = 1; + else if (v >= 20.9e3) + dur = (unsigned char)(5.35e6 / v); + else + dur = 255; + + return jtagmkII_setparm(pgm, PAR_OCD_JTAG_CLK, &dur); +} + + +/* + * Read an emulator parameter. As the maximal parameter length is 4 + * bytes by now, we always copy out 4 bytes to *value, so the caller + * must have allocated sufficient space. + */ +int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value) +{ + int status; + unsigned char buf[2], *resp, c; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_getparm()\n", progname); + + buf[0] = CMND_GET_PARAMETER; + buf[1] = parm; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_getparm(): " + "Sending get parameter command (parm 0x%02x): ", + progname, parm); + jtagmkII_send(pgm, buf, 2); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_getparm(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + if (c != RSP_PARAMETER) { + fprintf(stderr, + "%s: jtagmkII_getparm(): " + "bad response to get parameter command: %s\n", + progname, jtagmkII_get_rc(c)); + free(resp); + return -1; + } + + memcpy(value, resp + 1, 4); + free(resp); + + return 0; +} + +/* + * Write an emulator parameter. + */ +static int jtagmkII_setparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value) +{ + int status; + /* + * As the maximal parameter length is 4 bytes, we use a fixed-length + * buffer, as opposed to malloc()ing it. + */ + unsigned char buf[2 + 4], *resp, c; + size_t size; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_setparm()\n", progname); + + switch (parm) { + case PAR_HW_VERSION: size = 2; break; + case PAR_FW_VERSION: size = 4; break; + case PAR_EMULATOR_MODE: size = 1; break; + case PAR_BAUD_RATE: size = 1; break; + case PAR_OCD_VTARGET: size = 2; break; + case PAR_OCD_JTAG_CLK: size = 1; break; + case PAR_TIMERS_RUNNING: size = 1; break; + case PAR_EXTERNAL_RESET: size = 1; break; + case PAR_DAISY_CHAIN_INFO: size = 4; break; + case PAR_PDI_OFFSET_START: + case PAR_PDI_OFFSET_END: size = 4; break; + default: + fprintf(stderr, "%s: jtagmkII_setparm(): unknown parameter 0x%02x\n", + progname, parm); + return -1; + } + + buf[0] = CMND_SET_PARAMETER; + buf[1] = parm; + memcpy(buf + 2, value, size); + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_setparm(): " + "Sending set parameter command (parm 0x%02x, %u bytes): ", + progname, parm, (unsigned)size); + jtagmkII_send(pgm, buf, size + 2); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_setparm(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_setparm(): " + "bad response to set parameter command: %s\n", + progname, jtagmkII_get_rc(c)); + return -1; + } + + return 0; +} + + +static void jtagmkII_display(PROGRAMMER * pgm, const char * p) +{ + unsigned char hw[4], fw[4]; + + if (jtagmkII_getparm(pgm, PAR_HW_VERSION, hw) < 0 || + jtagmkII_getparm(pgm, PAR_FW_VERSION, fw) < 0) + return; + + fprintf(stderr, "%sM_MCU hardware version: %d\n", p, hw[0]); + fprintf(stderr, "%sM_MCU firmware version: %d.%02d\n", p, fw[1], fw[0]); + fprintf(stderr, "%sS_MCU hardware version: %d\n", p, hw[1]); + fprintf(stderr, "%sS_MCU firmware version: %d.%02d\n", p, fw[3], fw[2]); + fprintf(stderr, "%sSerial number: %02x:%02x:%02x:%02x:%02x:%02x\n", + p, PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]); + + jtagmkII_print_parms1(pgm, p); + + return; +} + + +static void jtagmkII_print_parms1(PROGRAMMER * pgm, const char * p) +{ + unsigned char vtarget[4], jtag_clock[4]; + char clkbuf[20]; + double clk; + + if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0) + return; + + fprintf(stderr, "%sVtarget : %.1f V\n", p, + b2_to_u16(vtarget) / 1000.0); + + if ((pgm->flag & PGM_FL_IS_JTAG)) { + if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0) + return; + + if (jtag_clock[0] == 0) { + strcpy(clkbuf, "6.4 MHz"); + clk = 6.4e6; + } else if (jtag_clock[0] == 1) { + strcpy(clkbuf, "2.8 MHz"); + clk = 2.8e6; + } else if (jtag_clock[0] <= 5) { + sprintf(clkbuf, "%.1f MHz", 5.35 / (double)jtag_clock[0]); + clk = 5.35e6 / (double)jtag_clock[0]; + } else { + sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]); + clk = 5.35e6 / (double)jtag_clock[0]; + + fprintf(stderr, "%sJTAG clock : %s (%.1f us)\n", p, clkbuf, + 1.0e6 / clk); + } + } + + return; +} + +static void jtagmkII_print_parms(PROGRAMMER * pgm) +{ + jtagmkII_print_parms1(pgm, ""); +} + +#ifdef __OBJC__ +#pragma mark - +#endif + +static int jtagmkII_avr32_reset(PROGRAMMER * pgm, unsigned char val, + unsigned char ret1, unsigned char ret2) +{ + int status; + unsigned char buf[3], *resp; + + if(verbose) fprintf(stderr, + "%s: jtagmkII_avr32_reset(%2.2x)\n", + progname, val); + + buf[0] = CMND_GET_IR; + buf[1] = 0x0C; + status = jtagmkII_send(pgm, buf, 2); + if(status < 0) return -1; + + status = jtagmkII_recv(pgm, &resp); + if (status != 2 || resp[0] != 0x87 || resp[1] != ret1) { + if(verbose) fprintf(stderr, + "%s: jtagmkII_avr32_reset(): " + "Get_IR, expecting %2.2x but got %2.2x\n", + progname, ret1, resp[1]); + + //return -1; + } + + buf[0] = CMND_GET_xxx; + buf[1] = 5; + buf[2] = val; + status = jtagmkII_send(pgm, buf, 3); + if(status < 0) return -1; + + status = jtagmkII_recv(pgm, &resp); + if (status != 2 || resp[0] != 0x87 || resp[1] != ret2) { + if(verbose) fprintf(stderr, + "%s: jtagmkII_avr32_reset(): " + "Get_XXX, expecting %2.2x but got %2.2x\n", + progname, ret2, resp[1]); + //return -1; + } + + return 0; +} + +// At init: AVR32_RESET_READ_IR | AVR32_RESET_READ_READ_CHIPINFO +static int jtagmkII_reset32(PROGRAMMER * pgm, unsigned short flags) +{ + int status, j, lineno; + unsigned char *resp, buf[3]; + unsigned long val=0; + unsigned long config0, config1; + + if(verbose) fprintf(stderr, + "%s: jtagmkII_reset32(%2.2x)\n", + progname, flags); + + status = -1; + + // Happens at the start of a programming operation + if(flags & AVR32_RESET_READ) { + buf[0] = CMND_GET_IR; + buf[1] = 0x11; + status = jtagmkII_send(pgm, buf, 2); + if(status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_recv(pgm, &resp); + if (status != 2 || resp[0] != 0x87 || resp[1] != 01) + {lineno = __LINE__; goto eRR;}; + } + + if(flags & (AVR32_RESET_WRITE | AVR32_SET4RUNNING)) { + // AVR_RESET(0x1F) + status = jtagmkII_avr32_reset(pgm, 0x1F, 0x01, 0x00); + if(status < 0) {lineno = __LINE__; goto eRR;} + // AVR_RESET(0x07) + status = jtagmkII_avr32_reset(pgm, 0x07, 0x11, 0x1F); + if(status < 0) {lineno = __LINE__; goto eRR;} + } + + //if(flags & AVR32_RESET_COMMON) + { + val = jtagmkII_read_SABaddr(pgm, AVR32_DS, 0x01); + if(val != 0) {lineno = __LINE__; goto eRR;} + val = jtagmkII_read_SABaddr(pgm, AVR32_DC, 0x01); + if(val != 0) {lineno = __LINE__; goto eRR;} + } + + if(flags & (AVR32_RESET_READ | AVR32_RESET_CHIP_ERASE)) { + status = jtagmkII_write_SABaddr(pgm, AVR32_DC, 0x01, + AVR32_DC_DBE | AVR32_DC_DBR); + if(status < 0) return -1; + } + + if(flags & (AVR32_RESET_WRITE | AVR32_SET4RUNNING)) { + status = jtagmkII_write_SABaddr(pgm, AVR32_DC, 0x01, + AVR32_DC_ABORT | AVR32_DC_RESET | AVR32_DC_DBE | AVR32_DC_DBR); + if(status < 0) return -1; + for(j=0; j<21; ++j) { + val = jtagmkII_read_SABaddr(pgm, AVR32_DS, 0x01); + } + if(val != 0x04000000) {lineno = __LINE__; goto eRR;} + + // AVR_RESET(0x00) + status = jtagmkII_avr32_reset(pgm, 0x00, 0x01, 0x07); + if(status < 0) {lineno = __LINE__; goto eRR;} + } +// if(flags & (AVR32_RESET_READ | AVR32_RESET_WRITE)) + { + for(j=0; j<2; ++j) { + val = jtagmkII_read_SABaddr(pgm, AVR32_DS, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if((val&0x05000020) != 0x05000020) {lineno = __LINE__; goto eRR;} + } + } + + //if(flags & (AVR32_RESET_READ | AVR32_RESET_WRITE | AVR32_RESET_CHIP_ERASE)) + { + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe7b00044); // mtdr 272, R0 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCSR, 0x01); + if(val != 0x00000001) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCCPU, 0x01); + if(val != 0x00000000) {lineno = __LINE__; goto eRR;} + } + + // Read chip configuration - common for all + if(flags & (AVR32_RESET_READ | AVR32_RESET_WRITE | AVR32_RESET_CHIP_ERASE)) { + for(j=0; j<2; ++j) { + val = jtagmkII_read_SABaddr(pgm, AVR32_DS, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if((val&0x05000020) != 0x05000020) {lineno = __LINE__; goto eRR;} + } + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe7b00044); // mtdr 272, R0 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCSR, 0x01); + if(val != 0x00000001) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCCPU, 0x01); + if(val != 0x00000000) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe1b00040); // mfsr R0, 256 + if(status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe7b00044); // mtdr 272, R0 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCSR, 0x01); + if(val != 0x00000001) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCCPU, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + config0 = val; // 0x0204098b + + status = jtagmkII_write_SABaddr(pgm, AVR32_DCEMU, 0x01, 0x00000000); + if(status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe5b00045); // mtdr R0, 276 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DS, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if((val&0x05000020) != 0x05000020) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe7b00044); // mtdr 272, R0 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCSR, 0x01); + if(val != 0x00000001) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCCPU, 0x01); + if(val != 0x00000000) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe1b00041); // mfsr R0, 260 + if(status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe7b00044); // mtdr 272, R0 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCSR, 0x01); + if(val != 0x00000001) {lineno = __LINE__; goto eRR;} + val = jtagmkII_read_SABaddr(pgm, AVR32_DCCPU, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + config1 = val; // 0x00800000 + + status = jtagmkII_write_SABaddr(pgm, AVR32_DCEMU, 0x01, 0x00000000); + if(status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe5b00045); // mtdr R0, 276 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, 0x00000010, 0x06); // need to recheck who does this... + if(val != 0x00000000) {lineno = __LINE__; goto eRR;} + } + + if(flags & AVR32_RESET_CHIP_ERASE) { + status = jtagmkII_avr32_reset(pgm, 0x1f, 0x01, 0x00); + if(status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_avr32_reset(pgm, 0x01, 0x11, 0x1f); + if(status < 0) {lineno = __LINE__; goto eRR;} + } + + if(flags & AVR32_SET4RUNNING) { + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe1b00014); // mfsr R0, 80 + if(status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe7b00044); // mtdr 272, R0 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCSR, 0x01); + if(val != 0x00000001) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DCCPU, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + config0 = val; // 0x0204098b + + status = jtagmkII_write_SABaddr(pgm, AVR32_DCEMU, 0x01, 0x00000000); + if(status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xe5b00045); // mfdr R0, 276 + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, AVR32_DS, 0x01); + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if((val&0x05000020) != 0x05000020) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, AVR32_DINST, 0x01, 0xd623d703); // retd + if(status < 0) {lineno = __LINE__; goto eRR;} + } + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_reset32(): " + "failed at line %d (status=%x val=%lx)\n", + progname, lineno, status, val); + return -1; +} + +static int jtagmkII_smc_init32(PROGRAMMER * pgm) +{ + int status, lineno; + unsigned long val; + + // HMATRIX 0xFFFF1000 + status = jtagmkII_write_SABaddr(pgm, 0xffff1018, 0x05, 0x04000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1024, 0x05, 0x04000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1008, 0x05, 0x04000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1078, 0x05, 0x04000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1088, 0x05, 0x04000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, 0xffff1018, 0x05, 0x08000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1024, 0x05, 0x08000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1008, 0x05, 0x08000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1078, 0x05, 0x08000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1088, 0x05, 0x08000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, 0xffff1018, 0x05, 0x10000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1024, 0x05, 0x10000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1008, 0x05, 0x10000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1078, 0x05, 0x10000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1088, 0x05, 0x10000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, 0xffff1018, 0x05, 0x00020000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1024, 0x05, 0x00020000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1008, 0x05, 0x00020000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1078, 0x05, 0x00020000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1088, 0x05, 0x00020000); + if (status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, 0xffff1018, 0x05, 0x02000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1024, 0x05, 0x02000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1008, 0x05, 0x02000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1078, 0x05, 0x02000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xffff1088, 0x05, 0x02000000); + if (status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_write_SABaddr(pgm, 0xfffe1c00, 0x05, 0x00010001); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xfffe1c04, 0x05, 0x05070a0b); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xfffe1c08, 0x05, 0x000b000c); + if (status < 0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_write_SABaddr(pgm, 0xfffe1c0c, 0x05, 0x00031103); + if (status < 0) {lineno = __LINE__; goto eRR;} + + // switchToClockSource + val = jtagmkII_read_SABaddr(pgm, 0xffff0c28, 0x05); + if (val != 0x00000000) {lineno = __LINE__; goto eRR;} // OSC 0 + status = jtagmkII_write_SABaddr(pgm, 0xffff0c28, 0x05, 0x0000607); + if (status < 0) {lineno = __LINE__; goto eRR;} + val = jtagmkII_read_SABaddr(pgm, 0xffff0c00, 0x05); + if (val != 0x00000000) {lineno = __LINE__; goto eRR;} // PLL 0 + status = jtagmkII_write_SABaddr(pgm, 0xffff0c00, 0x05, 0x0000004); + if (status < 0) {lineno = __LINE__; goto eRR;} // Power Manager + status = jtagmkII_write_SABaddr(pgm, 0xffff0c00, 0x05, 0x0000005); + if (status < 0) {lineno = __LINE__; goto eRR;} + + usleep(1000000); + + val = jtagmkII_read_SABaddr(pgm, 0xfffe1408, 0x05); + if (val != 0x0000a001) {lineno = __LINE__; goto eRR;} // PLL 0 + + // need a small delay to let clock stabliize + usleep(50*1000); + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_smc_init32(): " + "failed at line %d\n", + progname, lineno); + return -1; +} + + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int jtagmkII_initialize32(PROGRAMMER * pgm, AVRPART * p) +{ + int status, j; + unsigned char buf[6], *resp; + + if (jtagmkII_setparm(pgm, PAR_DAISY_CHAIN_INFO, PDATA(pgm)->jtagchain) < 0) { + fprintf(stderr, "%s: jtagmkII_initialize(): Failed to setup JTAG chain\n", + progname); + return -1; + } + + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n", + progname); + return -1; + } + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkII_initialize32(): Out of memory\n", + progname); + free(PDATA(pgm)->flash_pagecache); + return -1; + } + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + + for(j=0; j<2; ++j) { + buf[0] = CMND_GET_IR; + buf[1] = 0x1; + if(jtagmkII_send(pgm, buf, 2) < 0) + return -1; + status = jtagmkII_recv(pgm, &resp); + if(status <= 0 || resp[0] != 0x87) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_initialize32(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + free(resp); + + memset(buf, 0, sizeof(buf)); + buf[0] = CMND_GET_xxx; + buf[1] = 0x20; + if(jtagmkII_send(pgm, buf, 6) < 0) + return -1; + status = jtagmkII_recv(pgm, &resp); + if(status <= 0 || resp[0] != 0x87) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_initialize32(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + + if (status != 5 || + resp[2] != p->signature[0] || + resp[3] != p->signature[1] || + resp[4] != p->signature[2]) { + fprintf(stderr, + "%s: Expected signature for %s is %02X %02X %02X\n", + progname, p->desc, + p->signature[0], p->signature[1], p->signature[2]); + if (!ovsigck) { + fprintf(stderr, "%sDouble check chip, " + "or use -F to override this check.\n", + progbuf); + return -1; + } + } + free(resp); + } + + return 0; +} + +static int jtagmkII_chip_erase32(PROGRAMMER * pgm, AVRPART * p) +{ + int status=0, loops; + unsigned char *resp, buf[3], x, ret[4], *retP; + unsigned long val=0; + unsigned int lineno; + + if(verbose) fprintf(stderr, + "%s: jtagmkII_chip_erase32()\n", + progname); + + status = jtagmkII_reset32(pgm, AVR32_RESET_CHIP_ERASE); + if(status != 0) {lineno = __LINE__; goto eRR;} + + // sequence of IR transitions + ret[0] = 0x01; + ret[1] = 0x05; + ret[2] = 0x01; + ret[3] = 0x00; + + retP = ret; + for(loops=0; loops<1000; ++loops) { + buf[0] = CMND_GET_IR; + buf[1] = 0x0F; + status = jtagmkII_send(pgm, buf, 2); + if(status < 0) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_recv(pgm, &resp); + if (status != 2 || resp[0] != 0x87) { + {lineno = __LINE__; goto eRR;} + } + x = resp[1]; + free(resp); + if(x == *retP) ++retP; + if(*retP == 0x00) break; + } + if(loops == 1000) {lineno = __LINE__; goto eRR;} + + status = jtagmkII_avr32_reset(pgm, 0x00, 0x01, 0x01); + if(status < 0) {lineno = __LINE__; goto eRR;} + + val = jtagmkII_read_SABaddr(pgm, 0x00000010, 0x06); + if(val != 0x00000000) {lineno = __LINE__; goto eRR;} + + // AVR32 "special" + buf[0] = CMND_SET_PARAMETER; + buf[1] = 0x03; + buf[2] = 0x02; + jtagmkII_send(pgm, buf, 3); + status = jtagmkII_recv(pgm, &resp); + if(status < 0 || resp[0] != RSP_OK) {lineno = __LINE__; goto eRR;} + free(resp); + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_reset32(): " + "failed at line %d (status=%x val=%lx)\n", + progname, lineno, status, val); + return -1; +} + +static unsigned long jtagmkII_read_SABaddr(PROGRAMMER * pgm, unsigned long addr, + unsigned int prefix) +{ + unsigned char buf[6], *resp; + int status; + unsigned long val; + unsigned long otimeout = serial_recv_timeout; + + serial_recv_timeout = 256; + + buf[0] = CMND_READ_SAB; + buf[1] = prefix; + u32_to_b4r(&buf[2], addr); + + if(jtagmkII_send(pgm, buf, 6) < 0) + return ERROR_SAB; + + status = jtagmkII_recv(pgm, &resp); + if(status <= 0 || resp[0] != 0x87) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_read_SABaddr(): " + "timeout/error communicating with programmer (status %d) resp=%x\n", + progname, status, resp[0]); + serial_recv_timeout = otimeout; + + if(status > 0) { + int i; + fprintf(stderr, "Cmd: "); + for(i=0; i<6; ++i) fprintf(stderr, "%2.2x ", buf[i]); + fprintf(stderr, "\n"); + fprintf(stderr, "Data: "); + for(i=0; i= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_read_SABaddr(): " + "wrong number of bytes (status %d)\n", + progname, status); + serial_recv_timeout = otimeout; + return ERROR_SAB; + } + + val = b4_to_u32r(&resp[1]); + free(resp); + + if (verbose) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_read_SABaddr(): " + "OCD Register %lx -> %4.4lx\n", + progname, addr, val); + } + serial_recv_timeout = otimeout; + return val; +} + +static int jtagmkII_write_SABaddr(PROGRAMMER * pgm, unsigned long addr, + unsigned int prefix, unsigned long val) +{ + unsigned char buf[10], *resp; + int status; + + buf[0] = CMND_WRITE_SAB; + buf[1] = prefix; + u32_to_b4r(&buf[2], addr); + u32_to_b4r(&buf[6], val); + + if(jtagmkII_send(pgm, buf, 10) < 0) + return -1; + + status = jtagmkII_recv(pgm, &resp); + if(status <= 0 || resp[0] != RSP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_write_SABaddr(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return -1; + } + + + if (verbose) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_write_SABaddr(): " + "OCD Register %lx -> %4.4lx\n", + progname, addr, val); + } + return 0; +} + +static int jtagmkII_open32(PROGRAMMER * pgm, char * port) +{ + int status; + unsigned char buf[6], *resp; + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_open32()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_JTAGICEMKII; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + status = jtagmkII_getsync(pgm, -1); + if(status < 0) return -1; + + // AVR32 "special" + buf[0] = CMND_SET_PARAMETER; + buf[1] = 0x2D; + buf[2] = 0x03; + jtagmkII_send(pgm, buf, 3); + status = jtagmkII_recv(pgm, &resp); + if(status < 0 || resp[0] != RSP_OK) + return -1; + free(resp); + + buf[1] = 0x03; + buf[2] = 0x02; + jtagmkII_send(pgm, buf, 3); + status = jtagmkII_recv(pgm, &resp); + if(status < 0 || resp[0] != RSP_OK) + return -1; + free(resp); + + buf[1] = 0x03; + buf[2] = 0x04; + jtagmkII_send(pgm, buf, 3); + status = jtagmkII_recv(pgm, &resp); + if(status < 0 || resp[0] != RSP_OK) + return -1; + free(resp); + + return 0; +} + +static void jtagmkII_close32(PROGRAMMER * pgm) +{ + int status, lineno; + unsigned char *resp, buf[3], c; + unsigned long val=0; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_close32()\n", progname); + + // AVR32 "special" + buf[0] = CMND_SET_PARAMETER; + buf[1] = 0x03; + buf[2] = 0x02; + jtagmkII_send(pgm, buf, 3); + status = jtagmkII_recv(pgm, &resp); + if(status < 0 || resp[0] != RSP_OK) {lineno = __LINE__; goto eRR;} + free(resp); + + buf[0] = CMND_SIGN_OFF; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_close(): Sending sign-off command: ", + progname); + jtagmkII_send(pgm, buf, 1); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkII_close(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + return; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + c = resp[0]; + free(resp); + if (c != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_close(): " + "bad response to sign-off command: %s\n", + progname, jtagmkII_get_rc(c)); + } + + ret: + serial_close(&pgm->fd); + pgm->fd.ifd = -1; + return; + + eRR: + fprintf(stderr, + "%s: jtagmkII_reset32(): " + "failed at line %d (status=%x val=%lx)\n", + progname, lineno, status, val); + goto ret; +} + +static int jtagmkII_paged_load32(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned int addr, block_size; + unsigned char cmd[7]; + unsigned char *resp; + int lineno, status; + unsigned long val=0; + long otimeout = serial_recv_timeout; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_paged_load32(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + serial_recv_timeout = 256; + + if(!(p->flags & AVRPART_WRITE)) { + status = jtagmkII_reset32(pgm, AVR32_RESET_READ); + if(status != 0) {lineno = __LINE__; goto eRR;} + } + + // Init SMC and set clocks + if(!(p->flags & AVRPART_INIT_SMC)) { + status = jtagmkII_smc_init32(pgm); + if(status != 0) {lineno = __LINE__; goto eRR;} // PLL 0 + p->flags |= AVRPART_INIT_SMC; + } + + // Init SMC and set clocks + if(!(p->flags & AVRPART_INIT_SMC)) { + status = jtagmkII_smc_init32(pgm); + if(status != 0) {lineno = __LINE__; goto eRR;} // PLL 0 + p->flags |= AVRPART_INIT_SMC; + } + + //fprintf(stderr, "\n pageSize=%d bytes=%d pages=%d m->offset=0x%x pgm->page_size %d\n", + // page_size, n_bytes, pages, m->offset, pgm->page_size); + + cmd[0] = CMND_READ_MEMORY32; + cmd[1] = 0x40; + cmd[2] = 0x05; + + addr = 0; + for (addr = 0; addr < n_bytes; addr += block_size) { + report_progress(addr, n_bytes, NULL); + + block_size = ((n_bytes-addr) < pgm->page_size) ? (n_bytes - addr) : pgm->page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_paged_load32(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + u32_to_b4r(cmd + 3, m->offset + addr); + + status = jtagmkII_send(pgm, cmd, 7); + if(status<0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_recv(pgm, &resp); + if(status<0) {lineno = __LINE__; goto eRR;} + + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != 0x87) { + fprintf(stderr, + "%s: jtagmkII_paged_load32(): " + "bad response to write memory command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + free(resp); + return -1; + } + memcpy(m->buf + addr, resp + 1, block_size); + free(resp); + + } + + serial_recv_timeout = otimeout; + + status = jtagmkII_reset32(pgm, AVR32_SET4RUNNING); + if(status < 0) {lineno = __LINE__; goto eRR;} + + return addr; + + eRR: + serial_recv_timeout = otimeout; + fprintf(stderr, + "%s: jtagmkII_paged_load32(): " + "failed at line %d (status=%x val=%lx)\n", + progname, lineno, status, val); + return -1; +} + +static int jtagmkII_paged_write32(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned int addr, block_size; + unsigned char *cmd=NULL; + unsigned char *resp; + int lineno, status, pages, pageNum, blocks; + unsigned long val=0; + unsigned long otimeout = serial_recv_timeout; + + serial_recv_timeout = 256; + + if(n_bytes == 0) return -1; + + status = jtagmkII_reset32(pgm, AVR32_RESET_WRITE); + if(status != 0) {lineno = __LINE__; goto eRR;} + p->flags |= AVRPART_WRITE; + + pages = (n_bytes-1)/page_size + 1; + //fprintf(stderr, "\n pageSize=%d bytes=%d pages=%d m->offset=0x%x pgm->page_size %d\n", + // page_size, n_bytes, pages, m->offset, pgm->page_size); + + // Before any errors can happen + if ((cmd = malloc(pgm->page_size + 10)) == NULL) { + fprintf(stderr, "%s: jtagmkII_paged_write32(): Out of memory\n", progname); + return -1; + } + + // Init SMC and set clocks + if(!(p->flags & AVRPART_INIT_SMC)) { + status = jtagmkII_smc_init32(pgm); + if(status != 0) {lineno = __LINE__; goto eRR;} // PLL 0 + p->flags |= AVRPART_INIT_SMC; + } + + // First unlock the pages + for(pageNum=0; pageNum < pages; ++pageNum) { + status =jtagmkII_flash_lock32(pgm, 0, pageNum); + if(status < 0) {lineno = __LINE__; goto eRR;} + } + + // Then erase them (guess could do this in the same loop above?) + for(pageNum=0; pageNum < pages; ++pageNum) { + status =jtagmkII_flash_erase32(pgm, pageNum); + if(status < 0) {lineno = __LINE__; goto eRR;} + } + + cmd[0] = CMND_WRITE_MEMORY32; + u32_to_b4r(&cmd[1], 0x40000000); // who knows + cmd[5] = 0x5; + + addr = 0; + for(pageNum=0; pageNum < pages; ++pageNum) { + + report_progress(addr, n_bytes, NULL); + + status = jtagmkII_flash_clear_pagebuffer32(pgm); + if(status != 0) {lineno = __LINE__; goto eRR;} + + for(blocks=0; blocks<2; ++blocks) { + block_size = ((n_bytes-addr) < pgm->page_size) ? (n_bytes - addr) : pgm->page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkII_paged_write32(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + u32_to_b4r(cmd + 6, m->offset + addr); + memset(cmd + 10, 0xff, pgm->page_size); + memcpy(cmd + 10, m->buf + addr, block_size); + + status = jtagmkII_send(pgm, cmd, pgm->page_size + 10); + if(status<0) {lineno = __LINE__; goto eRR;} + status = jtagmkII_recv(pgm, &resp); + if (status<0) {lineno = __LINE__; goto eRR;} + + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_paged_write32(): " + "bad response to write memory command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + free(resp); + free(cmd); + return -1; + } + free(resp); + + addr += block_size; + + + } + status = jtagmkII_flash_write_page32(pgm, pageNum); + if(status < 0) {lineno = __LINE__; goto eRR;} + } + free(cmd); + serial_recv_timeout = otimeout; + + status = jtagmkII_reset32(pgm, AVR32_SET4RUNNING); // AVR32_SET4RUNNING | AVR32_RELEASE_JTAG + if(status < 0) {lineno = __LINE__; goto eRR;} + + return addr; + + eRR: + serial_recv_timeout = otimeout; + free(cmd); + fprintf(stderr, + "%s: jtagmkII_paged_write32(): " + "failed at line %d (status=%x val=%lx)\n", + progname, lineno, status, val); + return -1; +} + + +static int jtagmkII_flash_lock32(PROGRAMMER * pgm, unsigned char lock, unsigned int page) +{ + int status, lineno, i; + unsigned long val, cmd=0; + + for(i=0; i<256; ++i) { + val = jtagmkII_read_SABaddr(pgm, AVR32_FLASHC_FSR, 0x05); + if(val == ERROR_SAB) continue; + if(val & AVR32_FLASHC_FSR_RDY) break; + } + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if(!(val&AVR32_FLASHC_FSR_RDY)) {lineno = __LINE__; goto eRR;} // Flash better be ready + + page <<= 8; + cmd = AVR32_FLASHC_FCMD_KEY | page | (lock ? AVR32_FLASHC_FCMD_LOCK : AVR32_FLASHC_FCMD_UNLOCK); + status = jtagmkII_write_SABaddr(pgm, AVR32_FLASHC_FCMD, 0x05, cmd); + if (status < 0) {lineno = __LINE__; goto eRR;} + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_flash_lock32(): " + "failed at line %d page %d cmd %8.8lx\n", + progname, lineno, page, cmd); + return -1; +} + +static int jtagmkII_flash_erase32(PROGRAMMER * pgm, unsigned int page) +{ + int status, lineno, i; + unsigned long val=0, cmd=0, err=0; + + for(i=0; i<256; ++i) { + val = jtagmkII_read_SABaddr(pgm, AVR32_FLASHC_FSR, 0x05); + if(val == ERROR_SAB) continue; + if(val & AVR32_FLASHC_FSR_RDY) break; + } + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if(!(val&AVR32_FLASHC_FSR_RDY)) {lineno = __LINE__; goto eRR;} // Flash better be ready + + page <<= 8; + cmd = AVR32_FLASHC_FCMD_KEY | page | AVR32_FLASHC_FCMD_ERASE_PAGE; + status = jtagmkII_write_SABaddr(pgm, AVR32_FLASHC_FCMD, 0x05, cmd); + if (status < 0) {lineno = __LINE__; goto eRR;} + +//fprintf(stderr, "ERASE %x -> %x\n", cmd, AVR32_FLASHC_FCMD); + + err = 0; + for(i=0; i<256; ++i) { + val = jtagmkII_read_SABaddr(pgm, AVR32_FLASHC_FSR, 0x05); + if(val == ERROR_SAB) continue; + err |= val; + if(val & AVR32_FLASHC_FSR_RDY) break; + } + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if(!(val & AVR32_FLASHC_FSR_RDY)) {lineno = __LINE__; goto eRR;} + if(err & AVR32_FLASHC_FSR_ERR) {lineno = __LINE__; goto eRR;} + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_flash_erase32(): " + "failed at line %d page %d cmd %8.8lx val %lx\n", + progname, lineno, page, cmd, val); + return -1; +} + +static int jtagmkII_flash_write_page32(PROGRAMMER * pgm, unsigned int page) +{ + int status, lineno, i; + unsigned long val=0, cmd, err; + + page <<= 8; + cmd = AVR32_FLASHC_FCMD_KEY | page | AVR32_FLASHC_FCMD_WRITE_PAGE; + status = jtagmkII_write_SABaddr(pgm, AVR32_FLASHC_FCMD, 0x05, cmd); + if (status < 0) {lineno = __LINE__; goto eRR;} + + err = 0; + for(i=0; i<256; ++i) { + val = jtagmkII_read_SABaddr(pgm, AVR32_FLASHC_FSR, 0x05); + if(val == ERROR_SAB) continue; + err |= val; + if(val & AVR32_FLASHC_FSR_RDY) break; + } + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if(!(val & AVR32_FLASHC_FSR_RDY)) {lineno = __LINE__; goto eRR;} + if(err & AVR32_FLASHC_FSR_ERR) {lineno = __LINE__; goto eRR;} + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_flash_write_page32(): " + "failed at line %d page %d cmd %8.8lx val %lx\n", + progname, lineno, page, cmd, val); + return -1; +} + +static int jtagmkII_flash_clear_pagebuffer32(PROGRAMMER * pgm) +{ + int status, lineno, i; + unsigned long val=0, cmd, err; + + cmd = AVR32_FLASHC_FCMD_KEY | AVR32_FLASHC_FCMD_CLEAR_PAGE_BUFFER; + status = jtagmkII_write_SABaddr(pgm, AVR32_FLASHC_FCMD, 0x05, cmd); + if (status < 0) {lineno = __LINE__; goto eRR;} + + err = 0; + for(i=0; i<256; ++i) { + val = jtagmkII_read_SABaddr(pgm, AVR32_FLASHC_FSR, 0x05); + if(val == ERROR_SAB) continue; + err |= val; + if(val & AVR32_FLASHC_FSR_RDY) break; + } + if(val == ERROR_SAB) {lineno = __LINE__; goto eRR;} + if(!(val & AVR32_FLASHC_FSR_RDY)) {lineno = __LINE__; goto eRR;} + if(err & AVR32_FLASHC_FSR_ERR) {lineno = __LINE__; goto eRR;} + + return 0; + + eRR: + fprintf(stderr, + "%s: jtagmkII_flash_clear_pagebuffer32(): " + "failed at line %d cmd %8.8lx val %lx\n", + progname, lineno, cmd, val); + return -1; +} + +#ifdef __OBJC__ +#pragma mark - +#endif + +void jtagmkII_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKII"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase; + pgm->open = jtagmkII_open; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->set_sck_period = jtagmkII_set_sck_period; + pgm->parseextparams = jtagmkII_parseextparms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_JTAG; +} + +void jtagmkII_dw_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKII_DW"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase_dw; + pgm->open = jtagmkII_open_dw; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_DW; +} + + +void jtagmkII_pdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKII_PDI"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase; + pgm->open = jtagmkII_open_pdi; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_PDI; +} + + +void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_JTAG"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase; + pgm->open = jtagmkII_dragon_open; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->set_sck_period = jtagmkII_set_sck_period; + pgm->parseextparams = jtagmkII_parseextparms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_JTAG; +} + + +void jtagmkII_dragon_dw_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_DW"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase_dw; + pgm->open = jtagmkII_dragon_open_dw; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_DW; +} + +void jtagmkII_avr32_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKII_AVR32"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize32; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase32; + pgm->open = jtagmkII_open32; + pgm->close = jtagmkII_close32; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write32; + pgm->paged_load = jtagmkII_paged_load32; + pgm->print_parms = jtagmkII_print_parms; + //pgm->set_sck_period = jtagmkII_set_sck_period; + //pgm->parseextparams = jtagmkII_parseextparms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_JTAG; +} + +void jtagmkII_dragon_pdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_PDI"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkII_initialize; + pgm->display = jtagmkII_display; + pgm->enable = jtagmkII_enable; + pgm->disable = jtagmkII_disable; + pgm->program_enable = jtagmkII_program_enable_dummy; + pgm->chip_erase = jtagmkII_chip_erase; + pgm->open = jtagmkII_dragon_open_pdi; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_PDI; +} + diff --git a/avrdude/jtagmkII.h b/avrdude/jtagmkII.h new file mode 100644 index 00000000..22a15f82 --- /dev/null +++ b/avrdude/jtagmkII.h @@ -0,0 +1,57 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004, 2006 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef jtagmkII_h +#define jtagmkII_h + +#ifdef __cplusplus +extern "C" { +#endif + +int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len); +int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg); +void jtagmkII_close(PROGRAMMER * pgm); +int jtagmkII_getsync(PROGRAMMER * pgm, int mode); +int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value); + +void jtagmkII_initpgm (PROGRAMMER * pgm); +void jtagmkII_avr32_initpgm (PROGRAMMER * pgm); +void jtagmkII_dw_initpgm (PROGRAMMER * pgm); +void jtagmkII_pdi_initpgm (PROGRAMMER * pgm); +void jtagmkII_dragon_initpgm (PROGRAMMER * pgm); +void jtagmkII_dragon_dw_initpgm (PROGRAMMER * pgm); +void jtagmkII_dragon_pdi_initpgm (PROGRAMMER * pgm); + +/* + * These functions are referenced from stk500v2.c for JTAG ICE mkII + * and AVR Dragon programmers running in one of the STK500v2 + * modi. + */ +void jtagmkII_setup(PROGRAMMER * pgm); +void jtagmkII_teardown(PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/avrdude/jtagmkII_private.h b/avrdude/jtagmkII_private.h new file mode 100644 index 00000000..f5b423c1 --- /dev/null +++ b/avrdude/jtagmkII_private.h @@ -0,0 +1,363 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005, 2006 Joerg Wunsch + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + + +/* + * JTAG ICE mkII definitions + * Taken from Appnote AVR067 + */ + +#if !defined(JTAGMKII_PRIVATE_EXPORTED) +/* + * Communication with the JTAG ICE works in frames. The protocol + * somewhat resembles the STK500v2 protocol, yet it is sufficiently + * different to prevent a direct code reuse. :-( + * + * Frame format: + * + * +---------------------------------------------------------------+ + * | 0 | 1 . 2 | 3 . 4 . 5 . 6 | 7 | ... | N-1 . N | + * | | | | | | | + * | start | LSB MSB | LSB ....... MSB | token | msg | LSB MSB | + * | 0x1B | sequence# | message size | 0x0E | | CRC16 | + * +---------------------------------------------------------------+ + * + * Each request message will be returned by a response with a matching + * sequence #. Sequence # 0xffff is reserved for asynchronous event + * notifications that will be sent by the ICE without a request + * message (e.g. when the target hit a breakpoint). + * + * The message size excludes the framing overhead (10 bytes). + * + * The first byte of the message is always the request or response + * code, which is roughly classified as: + * + * . Messages (commands) use 0x00 through 0x3f. (The documentation + * claims that messages start at 0x01, but actually CMND_SIGN_OFF is + * 0x00.) + * . Internal commands use 0x40 through 0x7f (not documented). + * . Success responses use 0x80 through 0x9f. + * . Failure responses use 0xa0 through 0xbf. + * . Events use 0xe0 through 0xff. + */ +#define MESSAGE_START 0x1b +#define TOKEN 0x0e + +/* + * Max message size we are willing to accept. Prevents us from trying + * to allocate too much VM in case we received a nonsensical packet + * length. We have to allocate the buffer as soon as we've got the + * length information (and thus have to trust that information by that + * time at first), as the final CRC check can only be done once the + * entire packet came it. + */ +#define MAX_MESSAGE 100000 + +#endif /* JTAGMKII_PRIVATE_EXPORTED */ + +/* ICE command codes */ +#define CMND_CHIP_ERASE 0x13 +#define CMND_CLEAR_EVENTS 0x22 +#define CMND_CLR_BREAK 0x1A +#define CMND_ENTER_PROGMODE 0x14 +#define CMND_ERASEPAGE_SPM 0x0D +#define CMND_FORCED_STOP 0x0A +#define CMND_GET_BREAK 0x12 +#define CMND_GET_PARAMETER 0x03 +#define CMND_GET_SIGN_ON 0x01 +#define CMND_GET_SYNC 0x0f +#define CMND_GO 0x08 +#define CMND_ISP_PACKET 0x2F +#define CMND_LEAVE_PROGMODE 0x15 +#define CMND_READ_MEMORY 0x05 +#define CMND_READ_PC 0x07 +#define CMND_RESET 0x0B +#define CMND_RESTORE_TARGET 0x23 +#define CMND_RUN_TO_ADDR 0x1C +#define CMND_SELFTEST 0x10 +#define CMND_SET_BREAK 0x11 +#define CMND_SET_DEVICE_DESCRIPTOR 0x0C +#define CMND_SET_N_PARAMETERS 0x16 +#define CMND_SET_PARAMETER 0x02 +#define CMND_SIGN_OFF 0x00 +#define CMND_SINGLE_STEP 0x09 +#define CMND_SPI_CMD 0x1D +#define CMND_WRITE_MEMORY 0x04 +#define CMND_WRITE_PC 0x06 +#define CMND_XMEGA_ERASE 0x34 +// AVR32 - DFH +#define CMND_GET_IR 0x24 +#define CMND_GET_xxx 0x25 +#define CMND_WRITE_SAB 0x28 +#define CMND_READ_SAB 0x29 +#define CMND_RESET_AVR 0x2B +#define CMND_READ_MEMORY32 0x2C +#define CMND_WRITE_MEMORY32 0x2D + + +/* ICE responses */ +#define RSP_DEBUGWIRE_SYNC_FAILED 0xAC +#define RSP_FAILED 0xA0 +#define RSP_GET_BREAK 0x83 +#define RSP_ILLEGAL_BREAKPOINT 0xA8 +#define RSP_ILLEGAL_COMMAND 0xAA +#define RSP_ILLEGAL_EMULATOR_MODE 0xA4 +#define RSP_ILLEGAL_JTAG_ID 0xA9 +#define RSP_ILLEGAL_MCU_STATE 0xA5 +#define RSP_ILLEGAL_MEMORY_TYPE 0xA2 +#define RSP_ILLEGAL_MEMORY_RANGE 0xA3 +#define RSP_ILLEGAL_PARAMETER 0xA1 +#define RSP_ILLEGAL_POWER_STATE 0xAD +#define RSP_ILLEGAL_VALUE 0xA6 +#define RSP_MEMORY 0x82 +#define RSP_NO_TARGET_POWER 0xAB +#define RSP_OK 0x80 +#define RSP_PARAMETER 0x81 +#define RSP_PC 0x84 +#define RSP_SELFTEST 0x85 +#define RSP_SET_N_PARAMETERS 0xA7 +#define RSP_SIGN_ON 0x86 +#define RSP_SPI_DATA 0x88 + +/* ICE events */ +#define EVT_BREAK 0xE0 +#define EVT_DEBUG 0xE6 +#define EVT_ERROR_PHY_FORCE_BREAK_TIMEOUT 0xE2 +#define EVT_ERROR_PHY_MAX_BIT_LENGTH_DIFF 0xED +#define EVT_ERROR_PHY_OPT_RECEIVE_TIMEOUT 0xF9 +#define EVT_ERROR_PHY_OPT_RECEIVED_BREAK 0xFA +#define EVT_ERROR_PHY_RECEIVED_BREAK 0xF8 +#define EVT_ERROR_PHY_RECEIVE_TIMEOUT 0xF7 +#define EVT_ERROR_PHY_RELEASE_BREAK_TIMEOUT 0xE3 +#define EVT_ERROR_PHY_SYNC_OUT_OF_RANGE 0xF5 +#define EVT_ERROR_PHY_SYNC_TIMEOUT 0xF0 +#define EVT_ERROR_PHY_SYNC_TIMEOUT_BAUD 0xF4 +#define EVT_ERROR_PHY_SYNC_WAIT_TIMEOUT 0xF6 +#define EVT_RESULT_PHY_NO_ACTIVITY 0xFB +#define EVT_EXT_RESET 0xE7 +#define EVT_ICE_POWER_ERROR_STATE 0xEA +#define EVT_ICE_POWER_OK 0xEB +#define EVT_IDR_DIRTY 0xEC +#define EVT_NONE 0xEF +#define EVT_PDSB_BREAK 0xF2 +#define EVT_PDSMB_BREAK 0xF3 +#define EVT_PROGRAM_BREAK 0xF1 +#define EVT_RUN 0xE1 +#define EVT_TARGET_POWER_OFF 0xE5 +#define EVT_TARGET_POWER_ON 0xE4 +#define EVT_TARGET_SLEEP 0xE8 +#define EVT_TARGET_WAKEUP 0xE9 + +/* memory types for CMND_{READ,WRITE}_MEMORY */ +#define MTYPE_IO_SHADOW 0x30 /* cached IO registers? */ +#define MTYPE_SRAM 0x20 /* target's SRAM or [ext.] IO registers */ +#define MTYPE_EEPROM 0x22 /* EEPROM, what way? */ +#define MTYPE_EVENT 0x60 /* ICE event memory */ +#define MTYPE_SPM 0xA0 /* flash through LPM/SPM */ +#define MTYPE_FLASH_PAGE 0xB0 /* flash in programming mode */ +#define MTYPE_EEPROM_PAGE 0xB1 /* EEPROM in programming mode */ +#define MTYPE_FUSE_BITS 0xB2 /* fuse bits in programming mode */ +#define MTYPE_LOCK_BITS 0xB3 /* lock bits in programming mode */ +#define MTYPE_SIGN_JTAG 0xB4 /* signature in programming mode */ +#define MTYPE_OSCCAL_BYTE 0xB5 /* osccal cells in programming mode */ +#define MTYPE_CAN 0xB6 /* CAN mailbox */ +#define MTYPE_FLASH 0xc0 /* xmega flash - undocumented in AVR067 */ +#define MTYPE_USERSIG 0xc5 /* xmega user signature - undocumented in AVR067 */ +#define MTYPE_PRODSIG 0xc6 /* xmega production signature - undocumented in AVR067 */ + +/* (some) ICE parameters, for CMND_{GET,SET}_PARAMETER */ +#define PAR_HW_VERSION 0x01 +#define PAR_FW_VERSION 0x02 +#define PAR_EMULATOR_MODE 0x03 +# define EMULATOR_MODE_DEBUGWIRE 0x00 +# define EMULATOR_MODE_JTAG 0x01 +# define EMULATOR_MODE_HV 0x02 /* HVSP or PP mode of AVR Dragon */ +# define EMULATOR_MODE_SPI 0x03 +# define EMULATOR_MODE_JTAG_AVR32 0x04 +# define EMULATOR_MODE_JTAG_XMEGA 0x05 +# define EMULATOR_MODE_PDI 0x06 +#define PAR_IREG 0x04 +#define PAR_BAUD_RATE 0x05 +# define PAR_BAUD_2400 0x01 +# define PAR_BAUD_4800 0x02 +# define PAR_BAUD_9600 0x03 +# define PAR_BAUD_19200 0x04 /* default */ +# define PAR_BAUD_38400 0x05 +# define PAR_BAUD_57600 0x06 +# define PAR_BAUD_115200 0x07 +# define PAR_BAUD_14400 0x08 +#define PAR_OCD_VTARGET 0x06 +#define PAR_OCD_JTAG_CLK 0x07 +#define PAR_OCD_BREAK_CAUSE 0x08 +#define PAR_TIMERS_RUNNING 0x09 +#define PAR_BREAK_ON_CHANGE_FLOW 0x0A +#define PAR_BREAK_ADDR1 0x0B +#define PAR_BREAK_ADDR2 0x0C +#define PAR_COMBBREAKCTRL 0x0D +#define PAR_JTAGID 0x0E +#define PAR_UNITS_BEFORE 0x0F +#define PAR_UNITS_AFTER 0x10 +#define PAR_BIT_BEFORE 0x11 +#define PAR_BIT_ATER 0x12 +#define PAR_EXTERNAL_RESET 0x13 +#define PAR_FLASH_PAGE_SIZE 0x14 +#define PAR_EEPROM_PAGE_SIZE 0x15 +#define PAR_UNUSED1 0x16 +#define PAR_PSB0 0x17 +#define PAR_PSB1 0x18 +#define PAR_PROTOCOL_DEBUG_EVENT 0x19 +#define PAR_MCU_STATE 0x1A +# define STOPPED 0x00 +# define RUNNING 0x01 +# define PROGRAMMING 0x02 +#define PAR_DAISY_CHAIN_INFO 0x1B +#define PAR_BOOT_ADDRESS 0x1C +#define PAR_TARGET_SIGNATURE 0x1D +#define PAR_DEBUGWIRE_BAUDRATE 0x1E +#define PAR_PROGRAM_ENTRY_POINT 0x1F +#define PAR_PDI_OFFSET_START 0x32 +#define PAR_PDI_OFFSET_END 0x33 +#define PAR_PACKET_PARSING_ERRORS 0x40 +#define PAR_VALID_PACKETS_RECEIVED 0x41 +#define PAR_INTERCOMMUNICATION_TX_FAILURES 0x42 +#define PAR_INTERCOMMUNICATION_RX_FAILURES 0x43 +#define PAR_CRC_ERRORS 0x44 +#define PAR_POWER_SOURCE 0x45 +# define POWER_EXTERNAL 0x00 +# define POWER_USB 0x01 +#define PAR_CAN_FLAG 0x22 +# define DONT_READ_CAN_MAILBOX 0x00 +# define READ_CAN_MAILBOX 0x01 +#define PAR_ENABLE_IDR_IN_RUN_MODE 0x23 +# define ACCESS_OSCCAL 0x00 +# define ACCESS_IDR 0x01 +#define PAR_ALLOW_PAGEPROGRAMMING_IN_SCANCHAIN 0x24 +# define PAGEPROG_NOT_ALLOWED 0x00 +# define PAGEPROG_ALLOWED 0x01 + +/* Xmega erase memory types, for CMND_XMEGA_ERASE */ +#define XMEGA_ERASE_CHIP 0x00 +#define XMEGA_ERASE_APP 0x01 +#define XMEGA_ERASE_BOOT 0x02 +#define XMEGA_ERASE_EEPROM 0x03 +#define XMEGA_ERASE_APP_PAGE 0x04 +#define XMEGA_ERASE_BOOT_PAGE 0x05 +#define XMEGA_ERASE_EEPROM_PAGE 0x06 +#define XMEGA_ERASE_USERSIG 0x07 + +/* AVR32 related definitions */ +#define AVR32_FLASHC_FCR 0xFFFE1400 +#define AVR32_FLASHC_FCMD 0xFFFE1404 +#define AVR32_FLASHC_FCMD_KEY 0xA5000000 +#define AVR32_FLASHC_FCMD_WRITE_PAGE 1 +#define AVR32_FLASHC_FCMD_ERASE_PAGE 2 +#define AVR32_FLASHC_FCMD_CLEAR_PAGE_BUFFER 3 +#define AVR32_FLASHC_FCMD_LOCK 4 +#define AVR32_FLASHC_FCMD_UNLOCK 5 +#define AVR32_FLASHC_FSR 0xFFFE1408 +#define AVR32_FLASHC_FSR_RDY 0x00000001 +#define AVR32_FLASHC_FSR_ERR 0x00000008 +#define AVR32_FLASHC_FGPFRHI 0xFFFE140C +#define AVR32_FLASHC_FGPFRLO 0xFFFE1410 + +#define AVR32_DC 0x00000008 +#define AVR32_DS 0x00000010 +#define AVR32_DINST 0x00000104 +#define AVR32_DCCPU 0x00000110 +#define AVR32_DCEMU 0x00000114 +#define AVR32_DCSR 0x00000118 + +#define AVR32_DC_ABORT 0x80000000 +#define AVR32_DC_RESET 0x40000000 +#define AVR32_DC_DBE 0x00002000 +#define AVR32_DC_DBR 0x00001000 + +#define AVR32_RESET_READ 0x0001 +#define AVR32_RESET_WRITE 0x0002 +#define AVR32_RESET_CHIP_ERASE 0x0004 +#define AVR32_SET4RUNNING 0x0008 +//#define AVR32_RESET_COMMON (AVR32_RESET_READ | AVR32_RESET_WRITE | AVR32_RESET_CHIP_ERASE ) + + +#if !defined(JTAGMKII_PRIVATE_EXPORTED) +/* + * In appnote AVR067, struct device_descriptor is written with + * int/long field types. We cannot use them directly, as they were + * neither properly aligned for portability, nor did they care for + * endianess issues. We thus use arrays of unsigned chars, plus + * conversion macros. + */ +struct device_descriptor +{ + unsigned char ucReadIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucReadIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucWriteIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucWriteIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucReadExtIO[52]; /*LSB = IOloc 96, MSB = IOloc511 */ + unsigned char ucReadIOExtShadow[52]; /*LSB = IOloc 96, MSB = IOloc511 */ + unsigned char ucWriteExtIO[52]; /*LSB = IOloc 96, MSB = IOloc511 */ + unsigned char ucWriteIOExtShadow[52];/*LSB = IOloc 96, MSB = IOloc511 */ + unsigned char ucIDRAddress; /*IDR address */ + unsigned char ucSPMCRAddress; /*SPMCR Register address and dW BasePC */ + unsigned char ucRAMPZAddress; /*RAMPZ Register address in SRAM I/O */ + /*space */ + unsigned char uiFlashPageSize[2]; /*Device Flash Page Size, Size = */ + /*2 exp ucFlashPageSize */ + unsigned char ucEepromPageSize; /*Device Eeprom Page Size in bytes */ + unsigned char ulBootAddress[4]; /*Device Boot Loader Start Address */ + unsigned char uiUpperExtIOLoc[2]; /*Topmost (last) extended I/O */ + /*location, 0 if no external I/O */ + unsigned char ulFlashSize[4]; /*Device Flash Size */ + unsigned char ucEepromInst[20]; /*Instructions for W/R EEPROM */ + unsigned char ucFlashInst[3]; /*Instructions for W/R FLASH */ + unsigned char ucSPHaddr; /* stack pointer high */ + unsigned char ucSPLaddr; /* stack pointer low */ + /* new as of 16-02-2004 */ + unsigned char uiFlashpages[2]; /* number of pages in flash */ + unsigned char ucDWDRAddress; /* DWDR register address */ + unsigned char ucDWBasePC; /* base/mask value of the PC */ + /* new as of 30-04-2004 */ + unsigned char ucAllowFullPageBitstream; /* FALSE on ALL new */ + /*parts */ + unsigned char uiStartSmallestBootLoaderSection[2]; /* */ + /* new as of 18-10-2004 */ + unsigned char EnablePageProgramming; /* For JTAG parts only, */ + /* default TRUE */ + unsigned char ucCacheType; /* CacheType_Normal 0x00, */ + /* CacheType_CAN 0x01, */ + /* CacheType_HEIMDALL 0x02 */ + /* new as of 27-10-2004 */ + unsigned char uiSramStartAddr[2]; /* Start of SRAM */ + unsigned char ucResetType; /* Selects reset type. ResetNormal = 0x00 */ + /* ResetAT76CXXX = 0x01 */ + unsigned char ucPCMaskExtended; /* For parts with extended PC */ + unsigned char ucPCMaskHigh; /* PC high mask */ + unsigned char ucEindAddress; /* Selects reset type. [EIND address...] */ + /* new as of early 2005, firmware 4.x */ + unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */ +}; +#endif /* JTAGMKII_PRIVATE_EXPORTED */ + +/* return code from jtagmkII_getsync() to indicate a "graceful" + * failure, i.e. an attempt to enable ISP failed and should be + * eventually retried */ +#define JTAGII_GETSYNC_FAIL_GRACEFUL (-2) diff --git a/avrdude/jtagmkI_private.h b/avrdude/jtagmkI_private.h new file mode 100644 index 00000000..ec185c99 --- /dev/null +++ b/avrdude/jtagmkI_private.h @@ -0,0 +1,169 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005 Joerg Wunsch + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + + +/* + * JTAG ICE mkI definitions + */ + +/* ICE command codes */ +/* 0x20 Get Synch [Resp_OK] */ +#define CMD_GET_SYNC ' ' + +/* 0x31 Single Step [Sync_CRC/EOP] [Resp_OK] */ +/* 0x32 Read PC [Sync_CRC/EOP] [Resp_OK] [program counter] + * [Resp_OK] */ +/* 0x33 Write PC [program counter] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +/* 0xA2 Firmware Upgrade [upgrade string] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +/* 0xA0 Set Device Descriptor [device info] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +#define CMD_SET_DEVICE_DESCRIPTOR 0xA0 + +/* 0x42 Set Parameter [parameter] [setting] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +#define CMD_SET_PARAM 'B' + +/* 0x46 Forced Stop [Sync_CRC/EOP] [Resp_OK] [checksum][program + * counter] [Resp_OK] */ +#define CMD_STOP 'F' + +/* 0x47 Go [Sync_CRC/EOP] [Resp_OK] */ +#define CMD_GO 'G' + +/* 0x52 Read Memory [memory type] [word count] [start address] + * [Sync_CRC/EOP] [Resp_OK] [word 0] ... [word n] [checksum] + * [Resp_OK] */ +#define CMD_READ_MEM 'R' + +/* 0x53 Get Sign On [Sync_CRC/EOP] [Resp_OK] ["AVRNOCD"] [Resp_OK] */ +#define CMD_GET_SIGNON 'S' + +/* 0XA1 Erase Page spm [address] [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ + +/* 0x57 Write Memory [memory type] [word count] [start address] + * [Sync_CRC/EOP] [Resp_OK] [Cmd_DATA] [word 0] ... [word n] */ +#define CMD_WRITE_MEM 'W' + +/* Second half of write memory: the data command. Undocumented. */ +#define CMD_DATA 'h' + +/* 0x64 Get Debug Info [Sync_CRC/EOP] [Resp_OK] [0x00] [Resp_OK] */ +/* 0x71 Get Parameter [parameter] [Sync_CRC/EOP] [Resp_OK] [setting] + * [Resp_OK] */ +#define CMD_GET_PARAM 'q' + +/* 0x78 Reset [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_RESET 'x' + +/* 0xA3 Enter Progmode [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_ENTER_PROGMODE 0xa3 + +/* 0xA4 Leave Progmode [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_LEAVE_PROGMODE 0xa4 + +/* 0xA5 Chip Erase [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_CHIP_ERASE 0xa5 + + +/* ICE responses */ +#define RESP_OK 'A' +#define RESP_BREAK 'B' +#define RESP_INFO 'G' +#define RESP_FAILED 'F' +#define RESP_SYNC_ERROR 'E' +#define RESP_SLEEP 'H' +#define RESP_POWER 'I' + +#define PARM_BITRATE 'b' +#define PARM_SW_VERSION 0x7b +#define PARM_HW_VERSION 0x7a +#define PARM_IREG_HIGH 0x81 +#define PARM_IREG_LOW 0x82 +#define PARM_OCD_VTARGET 0x84 +#define PARM_OCD_BREAK_CAUSE 0x85 +#define PARM_CLOCK 0x86 +#define PARM_EXTERNAL_RESET 0x8b +#define PARM_FLASH_PAGESIZE_LOW 0x88 +#define PARM_FLASH_PAGESIZE_HIGH 0x89 +#define PARM_EEPROM_PAGESIZE 0x8a +#define PARM_TIMERS_RUNNING 0xa0 +#define PARM_BP_FLOW 0xa1 +#define PARM_BP_X_HIGH 0xa2 +#define PARM_BP_X_LOW 0xa3 +#define PARM_BP_Y_HIGH 0xa4 +#define PARM_BP_Y_LOW 0xa5 +#define PARM_BP_MODE 0xa6 +#define PARM_JTAGID_BYTE0 0xa7 +#define PARM_JTAGID_BYTE1 0xa8 +#define PARM_JTAGID_BYTE2 0xa9 +#define PARM_JTAGID_BYTE3 0xaa +#define PARM_UNITS_BEFORE 0xab +#define PARM_UNITS_AFTER 0xac +#define PARM_BIT_BEFORE 0xad +#define PARM_BIT_AFTER 0xae +#define PARM_PSB0_LOW 0xaf +#define PARM_PSBO_HIGH 0xb0 +#define PARM_PSB1_LOW 0xb1 +#define PARM_PSB1_HIGH 0xb2 +#define PARM_MCU_MODE 0xb3 + +#define JTAG_BITRATE_1_MHz 0xff +#define JTAG_BITRATE_500_kHz 0xfe +#define JTAG_BITRATE_250_kHz 0xfd +#define JTAG_BITRATE_125_kHz 0xfb + +/* memory types for CMND_{READ,WRITE}_MEMORY */ +#define MTYPE_IO_SHADOW 0x30 /* cached IO registers? */ +#define MTYPE_SRAM 0x20 /* target's SRAM or [ext.] IO registers */ +#define MTYPE_EEPROM 0x22 /* EEPROM, what way? */ +#define MTYPE_EVENT 0x60 /* ICE event memory */ +#define MTYPE_SPM 0xA0 /* flash through LPM/SPM */ +#define MTYPE_FLASH_PAGE 0xB0 /* flash in programming mode */ +#define MTYPE_EEPROM_PAGE 0xB1 /* EEPROM in programming mode */ +#define MTYPE_FUSE_BITS 0xB2 /* fuse bits in programming mode */ +#define MTYPE_LOCK_BITS 0xB3 /* lock bits in programming mode */ +#define MTYPE_SIGN_JTAG 0xB4 /* signature in programming mode */ +#define MTYPE_OSCCAL_BYTE 0xB5 /* osccal cells in programming mode */ + +struct device_descriptor +{ + unsigned char ucReadIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucWriteIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucReadIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucWriteIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucReadExtIO[20]; /*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucWriteExtIO[20]; /*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucReadIOExtShadow[20]; /*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucWriteIOExtShadow[20];/*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucIDRAddress; /*IDR address */ + unsigned char ucSPMCRAddress; /*SPMCR Register address and dW BasePC */ + unsigned char ucRAMPZAddress; /*RAMPZ Register address in SRAM I/O */ + /*space */ + unsigned char uiFlashPageSize[2]; /*Device Flash Page Size, Size = */ + /*2 exp ucFlashPageSize */ + unsigned char ucEepromPageSize; /*Device Eeprom Page Size in bytes */ + unsigned char ulBootAddress[4]; /*Device Boot Loader Start Address */ + unsigned char uiUpperExtIOLoc; /*Topmost (last) extended I/O */ + /*location, 0 if no external I/O */ +}; diff --git a/avrdude/lexer.l b/avrdude/lexer.l new file mode 100644 index 00000000..6f1698f8 --- /dev/null +++ b/avrdude/lexer.l @@ -0,0 +1,291 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +%{ +/* need this for the call to atof() below */ +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" + +#include "config.h" +#include "config_gram.h" +#include "lists.h" + +#define YY_NO_UNPUT + +%} + +DIGIT [0-9] +HEXDIGIT [0-9a-fA-F] +ID [_a-zA-Z][_a-zA-Z0-9]* +SIGN [+-] + +%x strng +%x incl +%x comment + +/* Bump resources for classic lex. */ +%e2000 +%p10000 +%n1000 + +%% + +{SIGN}*{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; } +{SIGN}*{DIGIT}+"."{DIGIT}* { yylval = number(yytext); return TKN_NUMBER; } +{SIGN}*"."{DIGIT}* { yylval = number(yytext); return TKN_NUMBER; } + +"\"" { string_buf_ptr = string_buf; BEGIN(strng); } + +0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; } + + + +# { /* The following eats '#' style comments to end of line */ + BEGIN(comment); } +[^\n] { /* eat comments */ } +\n { lineno++; BEGIN(INITIAL); } + + +"/*" { /* The following eats multiline C style comments */ + int c; + int comment_start; + + comment_start = lineno; + while (1) { + while (((c = input()) != '*') && (c != EOF)) { + /* eat up text of comment, but keep counting lines */ + if (c == '\n') + lineno++; + } + + if (c == '*') { + while ((c = input()) == '*') + ; + if (c == '/') + break; /* found the end */ + } + + if (c == EOF) { + fprintf(stderr, "error at %s:%d: EOF in comment\n", + infile, lineno); + fprintf(stderr, " comment started on line %d\n", + comment_start); + exit(1); + break; + } + } + } + + +\" { *string_buf_ptr = 0; string_buf_ptr = string_buf; + yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; } +\\n *string_buf_ptr++ = '\n'; +\\t *string_buf_ptr++ = '\t'; +\\r *string_buf_ptr++ = '\r'; +\\b *string_buf_ptr++ = '\b'; +\\f *string_buf_ptr++ = '\f'; +\\(.|\n) *(string_buf_ptr++) = yytext[1]; +[^\\\n\"]+ { char *yptr = yytext; while (*yptr) + *(string_buf_ptr++) = *(yptr++); } +\n { fprintf(stderr, "error at line %d: unterminated character constant\n", + lineno); + exit(1); } + +allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; } +arduino { yylval=NULL; return K_ARDUINO; } +avr910 { yylval=NULL; return K_AVR910; } +avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; } +avrftdi { yylval=NULL; return K_AVRFTDI; } +usbasp { yylval=NULL; return K_USBASP; } +usbtiny { yylval=NULL; return K_USBTINY; } +bank_size { yylval=NULL; return K_PAGE_SIZE; } +banked { yylval=NULL; return K_PAGED; } +baudrate { yylval=NULL; return K_BAUDRATE; } +bs2 { yylval=NULL; return K_BS2; } +buff { yylval=NULL; return K_BUFF; } +buspirate { yylval=NULL; return K_BUSPIRATE; } +butterfly { yylval=NULL; return K_BUTTERFLY; } +butterfly_mk { yylval=NULL; return K_BUTTERFLY_MK; } +chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; } +desc { yylval=NULL; return K_DESC; } +default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; } +default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } +default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } +default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; } +devicecode { yylval=NULL; return K_DEVICECODE; } +dragon_dw { yylval=NULL; return K_DRAGON_DW; } +dragon_hvsp { yylval=NULL; return K_DRAGON_HVSP; } +dragon_isp { yylval=NULL; return K_DRAGON_ISP; } +dragon_jtag { yylval=NULL; return K_DRAGON_JTAG; } +dragon_pdi { yylval=NULL; return K_DRAGON_PDI; } +dragon_pp { yylval=NULL; return K_DRAGON_PP; } +eecr { yylval=NULL; return K_EECR; } +eeprom { yylval=NULL; return K_EEPROM; } +enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; } +errled { yylval=NULL; return K_ERRLED; } +flash { yylval=NULL; return K_FLASH; } +has_jtag { yylval=NULL; return K_HAS_JTAG; } +has_debugwire { yylval=NULL; return K_HAS_DW; } +has_pdi { yylval=NULL; return K_HAS_PDI; } +has_tpi { yylval=NULL; return K_HAS_TPI; } +id { yylval=NULL; return K_ID; } +idr { yylval=NULL; return K_IDR; } +is_avr32 { yylval=NULL; return K_IS_AVR32; } +jtagmki { yylval=NULL; return K_JTAG_MKI; } +jtagmkii { yylval=NULL; return K_JTAG_MKII; } +jtagmkii_avr32 { yylval=NULL; return K_JTAG_MKII_AVR32; } +jtagmkii_dw { yylval=NULL; return K_JTAG_MKII_DW; } +jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; } +jtagmkii_pdi { yylval=NULL; return K_JTAG_MKII_PDI; } +max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } +memory { yylval=NULL; return K_MEMORY; } +min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; } +miso { yylval=NULL; return K_MISO; } +mosi { yylval=NULL; return K_MOSI; } +num_banks { yylval=NULL; return K_NUM_PAGES; } +num_pages { yylval=NULL; return K_NUM_PAGES; } +nvm_base { yylval=NULL; return K_NVM_BASE; } +offset { yylval=NULL; return K_OFFSET; } +page_size { yylval=NULL; return K_PAGE_SIZE; } +paged { yylval=NULL; return K_PAGED; } +pagel { yylval=NULL; return K_PAGEL; } +par { yylval=NULL; return K_PAR; } +parallel { yylval=NULL; return K_PARALLEL; } +part { yylval=NULL; return K_PART; } +pgmled { yylval=NULL; return K_PGMLED; } +programmer { yylval=NULL; return K_PROGRAMMER; } +pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; } +rampz { yylval=NULL; return K_RAMPZ; } +rdyled { yylval=NULL; return K_RDYLED; } +readback_p1 { yylval=NULL; return K_READBACK_P1; } +readback_p2 { yylval=NULL; return K_READBACK_P2; } +retry_pulse { yylval=NULL; return K_RETRY_PULSE; } +serbb { yylval=NULL; return K_SERBB; } +serial { yylval=NULL; return K_SERIAL; } +signature { yylval=NULL; return K_SIGNATURE; } +size { yylval=NULL; return K_SIZE; } +spmcr { yylval=NULL; return K_SPMCR; } +stk500 { yylval=NULL; return K_STK500; } +stk500hvsp { yylval=NULL; return K_STK500HVSP; } +stk500pp { yylval=NULL; return K_STK500PP; } +stk500v2 { yylval=NULL; return K_STK500V2; } +stk500generic { yylval=NULL; return K_STK500GENERIC; } +stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; } +stk600 { yylval=NULL; return K_STK600; } +stk600hvsp { yylval=NULL; return K_STK600HVSP; } +stk600pp { yylval=NULL; return K_STK600PP; } +type { yylval=NULL; return K_TYPE; } +usbdev { yylval=NULL; return K_USBDEV; } +usbpid { yylval=NULL; return K_USBPID; } +usbproduct { yylval=NULL; return K_USBPRODUCT; } +usbsn { yylval=NULL; return K_USBSN; } +usbvendor { yylval=NULL; return K_USBVENDOR; } +usbvid { yylval=NULL; return K_USBVID; } +vcc { yylval=NULL; return K_VCC; } +vfyled { yylval=NULL; return K_VFYLED; } +wiring { yylval=NULL; return K_WIRING; } + +timeout { yylval=NULL; return K_TIMEOUT; } +stabdelay { yylval=NULL; return K_STABDELAY; } +cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; } +hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; } +synchloops { yylval=NULL; return K_SYNCHLOOPS; } +bytedelay { yylval=NULL; return K_BYTEDELAY; } +pollvalue { yylval=NULL; return K_POLLVALUE; } +pollindex { yylval=NULL; return K_POLLINDEX; } +predelay { yylval=NULL; return K_PREDELAY; } +postdelay { yylval=NULL; return K_POSTDELAY; } +pollmethod { yylval=NULL; return K_POLLMETHOD; } +mode { yylval=NULL; return K_MODE; } +delay { yylval=NULL; return K_DELAY; } +blocksize { yylval=NULL; return K_BLOCKSIZE; } +readsize { yylval=NULL; return K_READSIZE; } +pp_controlstack { yylval=NULL; return K_PP_CONTROLSTACK; } +hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; } +hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; } +progmodedelay { yylval=NULL; return K_PROGMODEDELAY; } +latchcycles { yylval=NULL; return K_LATCHCYCLES; } +togglevtg { yylval=NULL; return K_TOGGLEVTG; } +poweroffdelay { yylval=NULL; return K_POWEROFFDELAY; } +resetdelayms { yylval=NULL; return K_RESETDELAYMS; } +resetdelayus { yylval=NULL; return K_RESETDELAYUS; } +hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; } +resetdelay { yylval=NULL; return K_RESETDELAY; } +synchcycles { yylval=NULL; return K_SYNCHCYCLES; } +chiperasepulsewidth { yylval=NULL; return K_CHIPERASEPULSEWIDTH; } +chiperasepolltimeout { yylval=NULL; return K_CHIPERASEPOLLTIMEOUT; } +chiperasetime { yylval=NULL; return K_CHIPERASETIME; } +programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; } +programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; } +programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; } +programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; } +flash_instr { yylval=NULL; return K_FLASH_INSTR; } +eeprom_instr { yylval=NULL; return K_EEPROM_INSTR; } + +dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; } +io { yylval=new_token(K_IO); return K_IO; } +pseudo { yylval=new_token(K_PSEUDO); return K_PSEUDO; } + +reset { yylval=new_token(K_RESET); return K_RESET; } +sck { yylval=new_token(K_SCK); return K_SCK; } + +read { yylval=new_token(K_READ); return K_READ; } +write { yylval=new_token(K_WRITE); return K_WRITE; } +read_lo { yylval=new_token(K_READ_LO); return K_READ_LO; } +read_hi { yylval=new_token(K_READ_HI); return K_READ_HI; } +write_lo { yylval=new_token(K_WRITE_LO); return K_WRITE_LO; } +write_hi { yylval=new_token(K_WRITE_HI); return K_WRITE_HI; } +loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; } +loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; } +load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); return K_LOAD_EXT_ADDR; } +writepage { yylval=new_token(K_WRITEPAGE); return K_WRITEPAGE; } +chip_erase { yylval=new_token(K_CHIP_ERASE); return K_CHIP_ERASE; } +pgm_enable { yylval=new_token(K_PGM_ENABLE); return K_PGM_ENABLE; } + +no { yylval=new_token(K_NO); return K_NO; } +yes { yylval=new_token(K_YES); return K_YES; } + +"," { yylval = NULL; pyytext(); return TKN_COMMA; } +"=" { yylval = NULL; pyytext(); return TKN_EQUAL; } +";" { yylval = NULL; pyytext(); return TKN_SEMI; } +"~" { yylval = NULL; pyytext(); return TKN_TILDE; } + +"\n" { lineno++; } +[ \r\t]+ { /* ignore whitespace */ } + +c: { fprintf(stderr, "error at %s:%d: possible old-style config file entry\n", + infile, lineno); + fprintf(stderr, " Update your config file (see %s%s for a sample)\n", + CONFIG_DIR, "/avrdude.conf.sample"); + exit(1); } + +. { fprintf(stderr, "error at %s:%d unrecognized character: \"%s\"\n", + infile, lineno, yytext); exit(1); } + +%% + diff --git a/avrdude/linux_ppdev.h b/avrdude/linux_ppdev.h new file mode 100644 index 00000000..15043961 --- /dev/null +++ b/avrdude/linux_ppdev.h @@ -0,0 +1,57 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003, 2005 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef linux_ppdev_h +#define linux_ppdev_h + +#define OBSOLETE__IOW _IOW + +#include +#include +#include + +#include + +#define ppi_claim(fd) \ + if (ioctl(fd, PPCLAIM)) { \ + fprintf(stderr, "%s: can't claim device \"%s\": %s\n\n", \ + progname, port, strerror(errno)); \ + close(fd); \ + exit(1); \ + } + +#define ppi_release(fd) \ + if (ioctl(fd, PPRELEASE)) { \ + fprintf(stderr, "%s: can't release device: %s\n\n", \ + progname, strerror(errno)); \ + exit(1); \ + } + +#define DO_PPI_READ(fd, reg, valp) \ + (void)ioctl(fd, \ + (reg) == PPIDATA? PPRDATA: ((reg) == PPICTRL? PPRCONTROL: PPRSTATUS), \ + valp) +#define DO_PPI_WRITE(fd, reg, valp) \ + (void)ioctl(fd, \ + (reg) == PPIDATA? PPWDATA: ((reg) == PPICTRL? PPWCONTROL: PPWSTATUS), \ + valp) + +#endif /* linux_ppdev_h */ diff --git a/avrdude/lists.c b/avrdude/lists.c new file mode 100644 index 00000000..3d1cfc64 --- /dev/null +++ b/avrdude/lists.c @@ -0,0 +1,1371 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 1990-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + /* $Id$ */ + + + +/*---------------------------------------------------------------------- + Id: lists.c,v 1.4 2001/08/19 23:26:20 bsd Exp $ + ----------------------------------------------------------------------*/ +/*------------------------------------------------------------------------ + lists.c + + General purpose linked list routines. These routines implement a + generic doubly linked list. Any data type may be placed in the + lists. Stacking and Queuing routines are provided via #defines + declared in 'lists.h'. + + Author : Brian Dean + Date : 10 January, 1990 + ------------------------------------------------------------------------*/ + +#include "ac_cfg.h" + +#include +#include + +#include "lists.h" + +#define MAGIC 0xb05b05b0 + +#define CHECK_MAGIC 0 /* set to 1 to enable memory overwrite detection */ + +#ifdef BOS +#define MALLOC(size,x) kmalloc(size,x) +#define FREE kfree +#else +#define MALLOC(size,x) malloc(size) +#define FREE free +#endif + + +/*------------------------------------------------------------ +| required private data structures + ------------------------------------------------------------*/ +typedef struct LISTNODE { +#if CHECK_MAGIC + unsigned int magic1; +#endif + struct LISTNODE * next; /* chain to next item in the list */ + struct LISTNODE * prev; /* chain to previous item in the list */ + void * data; /* pointer to user data */ +#if CHECK_MAGIC + unsigned int magic2; +#endif +} LISTNODE; + + +typedef struct NODEPOOL { +#if CHECK_MAGIC + unsigned int magic1; +#endif + struct NODEPOOL * chain_next; /* chain to next node pool */ + struct NODEPOOL * chain_prev; /* chain to previous node pool */ +#if CHECK_MAGIC + unsigned int magic2; +#endif +} NODEPOOL; + + +typedef struct LIST { +#if CHECK_MAGIC + unsigned int magic1; +#endif + int num; /* number of elements in the list */ + short int free_on_close; /* free the LIST memory on close T/F */ + short int poolsize; /* list node allocation size */ + int n_ln_pool; /* number of listnodes in a pool */ + LISTNODE * top; /* top of the list */ + LISTNODE * bottom; /* bottom of the list */ + LISTNODE * next_ln; /* next available list node */ + NODEPOOL * np_top; /* top of the node pool chain */ + NODEPOOL * np_bottom; /* bottom of the node pool chain */ +#if CHECK_MAGIC + unsigned int magic2; +#endif +} LIST; + + +/* allocate list nodes in 512 byte chunks, giving 42 elements */ +#define DEFAULT_POOLSIZE 512 + + +#if CHECK_MAGIC +#define CKMAGIC(p) { if (p->magic1 != MAGIC) breakpoint(); \ + if (p->magic2 != MAGIC) breakpoint(); } + +#define CKNPMAGIC(p) cknpmagic(p) + +#define CKLNMAGIC(p) cklnmagic(p) + +#define CKLMAGIC(p) cklmagic(p) +#else +#define CKMAGIC(p) + +#define CKNPMAGIC(p) + +#define CKLNMAGIC(p) + +#define CKLMAGIC(p) +#endif + + +static int insert_ln ( LIST * l, LISTNODE * ln, void * data_ptr ); + + +#if CHECK_MAGIC +static int cknpmagic ( LIST * l ) +{ + NODEPOOL * np; + int i; + + i = 0; + np = l->np_top; + while (np) { + i++; + CKMAGIC(np); + np = np->chain_next; + } + + i = 0; + np = l->np_bottom; + while (np) { + i++; + CKMAGIC(np); + np = np->chain_prev; + } + + return 0; +} + + + +static int cklnmagic ( LIST * l ) +{ + LISTNODE * ln; + int i; + + i = 0; + ln = l->top; + while (ln) { + i++; + CKMAGIC(ln); + ln = ln->next; + } + + i = 0; + ln = l->bottom; + while (ln) { + i++; + CKMAGIC(ln); + ln = ln->prev; + } + + return 0; +} + + +static int cklmagic ( LIST * l ) +{ + CKMAGIC(l); + CKNPMAGIC(l); + CKLNMAGIC(l); + CKMAGIC(l); + return 0; +} +#endif + + +/*------------------------------------------------------------ +| new_node_pool +| +| Create and initialize a new pool of list nodes. This is +| just a big block of memory with the first sizeof(NODEPOOL) +| bytes reserved. The first available list node resides at +| offset sizeof(NODEPOOL). + ------------------------------------------------------------*/ +static +NODEPOOL * +new_nodepool ( LIST * l ) +{ + NODEPOOL * np; + LISTNODE * ln; + int i; + + CKLMAGIC(l); + + /*-------------------------------------------------- + | get a block of memory for the new pool + --------------------------------------------------*/ + np = (NODEPOOL *) MALLOC ( l->poolsize, "list node pool" ); + if (np == NULL) { + return NULL; + } + + /*-------------------------------------------------- + | initialize the chaining information at the + | beginning of the pool. + --------------------------------------------------*/ +#if CHECK_MAGIC + np->magic1 = MAGIC; +#endif + np->chain_next = NULL; + np->chain_prev = NULL; +#if CHECK_MAGIC + np->magic2 = MAGIC; +#endif + + /*-------------------------------------------------- + | initialize all the list nodes within the node + | pool, which begin just after the NODEPOOL + | structure at the beginning of the memory block + --------------------------------------------------*/ + ln = (LISTNODE *) (&np[1]); + +#if CHECK_MAGIC + ln[0].magic1 = MAGIC; +#endif + ln[0].data = NULL; + ln[0].next = &ln[1]; + ln[0].prev = NULL; +#if CHECK_MAGIC + ln[0].magic2 = MAGIC; +#endif + + for (i=1; in_ln_pool-1; i++) { +#if CHECK_MAGIC + ln[i].magic1 = MAGIC; +#endif + ln[i].data = NULL; + ln[i].next = &ln[i+1]; + ln[i].prev = &ln[i-1]; +#if CHECK_MAGIC + ln[i].magic2 = MAGIC; +#endif + } + +#if CHECK_MAGIC + ln[l->n_ln_pool-1].magic1 = MAGIC; +#endif + ln[l->n_ln_pool-1].data = NULL; + ln[l->n_ln_pool-1].next = NULL; + ln[l->n_ln_pool-1].prev = &ln[l->n_ln_pool-2]; +#if CHECK_MAGIC + ln[l->n_ln_pool-1].magic2 = MAGIC; +#endif + + CKMAGIC(np); + + CKLMAGIC(l); + + return np; +} + + + +/*------------------------------------------------------------ +| get_listnode +| +| Get the next available list node. If there are no more +| list nodes, another pool of list nodes is allocated. If +| that fails, NULL is returned. + ------------------------------------------------------------*/ +static +LISTNODE * +get_listnode ( LIST * l ) +{ + LISTNODE * ln; + NODEPOOL * np; + + CKLMAGIC(l); + + if (l->next_ln == NULL) { + /*-------------------------------------------------- + | allocate a new node pool and chain to the others + --------------------------------------------------*/ + np = new_nodepool(l); + if (np == NULL) { + CKLMAGIC(l); + return NULL; + } + + if (l->np_top == NULL) { + /*-------------------------------------------------- + | this is the first node pool for this list, + | directly assign to the top and bottom. + --------------------------------------------------*/ + l->np_top = np; + l->np_bottom = np; + np->chain_next = NULL; + np->chain_prev = NULL; + } + else { + /*-------------------------------------------------- + | this is an additional node pool, add it to the + | chain. + --------------------------------------------------*/ + np->chain_next = NULL; + np->chain_prev = l->np_bottom; + l->np_bottom->chain_next = np; + l->np_bottom = np; + } + + /*-------------------------------------------------- + | set the list's pointer to the next available + | list node to the first list node in this new + | pool. + --------------------------------------------------*/ + l->next_ln = (LISTNODE *)&np[1]; + + CKMAGIC(np); + } + + /*-------------------------------------------------- + | get the next available list node, set the list's + | next available list node to the next one in the + | list. + --------------------------------------------------*/ + ln = l->next_ln; + l->next_ln = ln->next; + + CKMAGIC(ln); + + /*-------------------------------------------------- + | initialize the new list node and return + --------------------------------------------------*/ + ln->next = NULL; + ln->prev = NULL; + ln->data = NULL; + + CKLMAGIC(l); + + return ln; +} + + + +/*------------------------------------------------------------ +| free_listnode +| +| Return a list node to the pool of list nodes. This puts +| the node at the head of the free list, so that the next +| call to 'get_listnode', with return the most recently +| freed one. + ------------------------------------------------------------*/ +static +int +free_listnode ( LIST * l, LISTNODE * ln ) +{ + CKLMAGIC(l); + + /*-------------------------------------------------- + | insert the list node at the head of the list of + | free list nodes. + --------------------------------------------------*/ + ln->prev = NULL; + ln->data = NULL; + ln->next = l->next_ln; + l->next_ln = ln; + + CKLMAGIC(l); + + return 0; +} + + + +/*---------------------------------------------------------------------- + lcreat + + Create a new list data structure. + + If liststruct is not NULL, it is used to provide the memory space + for the list structure instance, otherwise, the necessary memory is + malloc'd. + + If elements is zero, the default poolsize is used, otherwise, + poolsizes of 'elements' elements are malloc'd to obtain the memory + for list nodes. Minimum element count is 5. + + The first node pool is not preallocated; instead it is malloc'd at + the time of the first use. + ----------------------------------------------------------------------*/ +LISTID +lcreat ( void * liststruct, int elements ) +{ + LIST * l; + + if (liststruct == NULL) { + /*-------------------------------------------------- + allocate memory for the list itself + --------------------------------------------------*/ + l = (LIST *) MALLOC ( sizeof(LIST), "list struct" ); + if (l == NULL) { + return NULL; + } + l->free_on_close = 1; + } + else { + /*----------------------------------------------------------------- + use the memory given to us for the list structure + -----------------------------------------------------------------*/ + l = liststruct; + l->free_on_close = 0; + } + + /*-------------------------------------------------- + | initialize the list + --------------------------------------------------*/ +#if CHECK_MAGIC + l->magic1 = MAGIC; + l->magic2 = MAGIC; +#endif + l->top = NULL; + l->bottom = NULL; + l->num = 0; + + if (elements == 0) { + l->poolsize = DEFAULT_POOLSIZE; + } + else { + l->poolsize = elements*sizeof(LISTNODE)+sizeof(NODEPOOL); + } + + l->n_ln_pool = (l->poolsize-sizeof(NODEPOOL))/sizeof(LISTNODE); + + if (l->n_ln_pool < 5) { + if (!liststruct) { + FREE(l); + } + return NULL; + } + + l->np_top = NULL; + l->np_bottom = NULL; + l->next_ln = NULL; + + CKLMAGIC(l); + + return (LISTID)l; +} + + +/*-------------------------------------------------- +| ldestroy_cb +| +| destroy an existing list data structure, calling +| the user routine 'ucleanup' on the data pointer +| of each list element. Allows the user to free +| up a list data structure and have this routine +| call their function to free up each list element +| at the same time. + --------------------------------------------------*/ +void +ldestroy_cb ( LISTID lid, void (*ucleanup)() ) +{ + LIST * l; + LISTNODE * ln; + + l = (LIST *)lid; + + CKLMAGIC(l); + + ln = l->top; + while (ln != NULL) { + ucleanup ( ln->data ); + ln = ln->next; + } + + ldestroy ( l ); +} + + + +/*-------------------------------------------------- +| ldestroy +| +| destroy an existing list data structure. +| +| assumes that each data element does not need to +| be freed. + --------------------------------------------------*/ +void +ldestroy ( LISTID lid ) +{ + LIST * l; + NODEPOOL * p1, * p2; + + l = (LIST *)lid; + + CKLMAGIC(l); + + /*-------------------------------------------------- + | free each node pool - start at the first node + | pool and free each successive until there are + | no more. + --------------------------------------------------*/ + p1 = l->np_top; + while (p1 != NULL) { + p2 = p1->chain_next; + FREE(p1); + p1 = p2; + } + + /*-------------------------------------------------- + | now free the memory occupied by the list itself + --------------------------------------------------*/ + if (l->free_on_close) { + FREE ( l ); + } +} + + + + +/*------------------------------------------------------------ +| ladd +| +| add list - add item p to the list + ------------------------------------------------------------*/ +int +ladd ( LISTID lid, void * p ) +{ + LIST * l; + LISTNODE *lnptr; + + l = (LIST *)lid; + + CKLMAGIC(l); + + lnptr = get_listnode(l); + if (lnptr==NULL) { +#ifdef BOS + breakpoint(); +#endif + return -1; + } + + CKMAGIC(lnptr); + + lnptr->data = p; + + if (l->top == NULL) { + l->top = lnptr; + l->bottom = lnptr; + lnptr->next = NULL; + lnptr->prev = NULL; + } + else { + lnptr->prev = l->bottom; + lnptr->next = NULL; + l->bottom->next = lnptr; + l->bottom = lnptr; + } + l->num++; + + CKLMAGIC(l); + + return 0; +} + + + +/*------------------------------------------------------------ +| laddo +| +| add list, ordered - add item p to the list, use 'compare' +| function to place 'p' when the comparison 'p' is less than +| the next item. Return 0 if this was a unique entry, +| else return 1 indicating a duplicate entry, i.e., the +| compare function returned 0 while inserting the element. + ------------------------------------------------------------*/ +int +laddo ( LISTID lid, void * p, int (*compare)(const void *p1,const void *p2), + LNODEID * firstdup ) +{ + LIST * l; + LISTNODE * ln; + int dup, cmp; + + l = (LIST *)lid; + + CKLMAGIC(l); + + dup = 0; + ln = l->top; + + while (ln!=NULL) { + CKMAGIC(ln); + cmp = compare(p,ln->data); + if (cmp == 0) { + dup = 1; + if (firstdup) + *firstdup = ln; + } + if (cmp < 0) { + insert_ln(l,ln,p); + CKLMAGIC(l); + return dup; + } + else { + ln = ln->next; + } + } + + ladd(l,p); + + CKLMAGIC(l); + + return dup; +} + + +/*--------------------------------------------------------------------------- +| laddu +| +| add list, ordered, unique - add item p to the list, use 'compare' +| function to place 'p' when the comparison 'p' is less than the next +| item. Return 1 if the item was added, 0 if not. +| + --------------------------------------------------------------------------*/ +int +laddu ( LISTID lid, void * p, int (*compare)(const void *p1,const void *p2) ) +{ + LIST * l; + LISTNODE * ln; + int cmp; + + l = (LIST *)lid; + + CKLMAGIC(l); + + ln = l->top; + + while (ln!=NULL) { + CKMAGIC(ln); + cmp = compare(p,ln->data); + if (cmp == 0) { + CKLMAGIC(l); + return 0; + } + if (cmp < 0) { + insert_ln(l,ln,p); + CKLMAGIC(l); + return 1; + } + else { + ln = ln->next; + } + } + + ladd(l,p); + + CKLMAGIC(l); + + return 1; +} + + + + +LNODEID +lfirst ( LISTID lid ) +{ + CKLMAGIC(((LIST *)lid)); + return ((LIST *)lid)->top; +} + + +LNODEID +llast ( LISTID lid ) +{ + CKLMAGIC(((LIST *)lid)); + return ((LIST *)lid)->bottom; +} + + +LNODEID +lnext ( LNODEID lnid ) +{ + CKMAGIC(((LISTNODE *)lnid)); + return ((LISTNODE *)lnid)->next; +} + + +LNODEID +lprev ( LNODEID lnid ) +{ + CKMAGIC(((LISTNODE *)lnid)); + return ((LISTNODE *)lnid)->prev; +} + + +void * +ldata ( LNODEID lnid ) +{ + CKMAGIC(((LISTNODE *)lnid)); + return ((LISTNODE *)lnid)->data; +} + + + +int +lsize ( LISTID lid ) +{ + CKLMAGIC(((LIST *)lid)); + return ((LIST *)lid)->num; +} + + + +/*------------------------------------------------------------ +| lcat +| +| catenate - catenate l2 to l1, return pointer to l1. + ------------------------------------------------------------*/ +LISTID +lcat ( LISTID lid1, LISTID lid2 ) +{ + CKLMAGIC(((LIST *)lid1)); + CKLMAGIC(((LIST *)lid2)); + while (lsize(lid2)) { + ladd ( lid1, lrmv_n(lid2,1) ); + } + + CKLMAGIC(((LIST *)lid1)); + CKLMAGIC(((LIST *)lid2)); + + return lid1; +} + + + +/*---------------------------------------------------------------------- +| lget +| +| get from list, last item - return pointer to the data of the last +| item in the list, non-destructive + ----------------------------------------------------------------------*/ +void * +lget ( LISTID lid ) +{ + LIST * l; + LISTNODE * p; + + l = (LIST *)lid; + + CKLMAGIC(l); + + p = l->bottom; + + if (p == NULL) { + CKLMAGIC(l); + return NULL; + } + else { + CKLMAGIC(l); + return p->data; + } +} + + + +/*--------------------------------------------------------------- +| lget_n +| +| get from list, index - return the nth list item, +| non-destructive + ---------------------------------------------------------------*/ +void * +lget_n ( LISTID lid, unsigned int n ) +{ + int i; + LIST * l; + LISTNODE * ln; + + l = (LIST *)lid; + + CKLMAGIC(l); + + if ((n<1)||(n>lsize(l))) { + return NULL; + } + + ln = l->top; + i = 1; + while (ln && (i!=n)) { + CKMAGIC(ln); + ln = ln->next; + i++; + } + + if (ln) { + CKLMAGIC(l); + return ln->data; + } + else { + CKLMAGIC(l); + return NULL; + } +} + + + +/*--------------------------------------------------------------- +| lget_ln +| +| get from list, listnode - return the nth list item, the +| listnode is returned instead of the data, non-destructive + ---------------------------------------------------------------*/ +LNODEID +lget_ln ( LISTID lid, unsigned int n ) +{ + int i; + LIST * l; + LISTNODE * ln; + + l = (LIST *)lid; + + CKLMAGIC(l); + + if ((n<1)||(n>lsize(l))) { + return NULL; + } + + ln = l->top; + i = 1; + while (i!=n) { + CKMAGIC(ln); + ln = ln->next; + i++; + } + + CKLMAGIC(l); + return (LNODEID)ln; +} + + + +/*---------------------------------------------------------------------- +| insert_ln +| +| insert data, listnode - insert data just before the list item +| pointed to by 'ln'. +| +| This routine is not intended to be called directly by the user +| because the validity of ln is not checked. This routine is called +| by list manipulation routines within this module, in which ln is +| known to point to a valid list node. + ----------------------------------------------------------------------*/ +static +int +insert_ln ( LIST * l, LISTNODE * ln, void * data_ptr ) +{ + LISTNODE * lnptr; + + CKLMAGIC(l); + + if (ln==NULL) { + ladd ( l, data_ptr ); + CKLMAGIC(l); + return 0; + } + + lnptr = get_listnode(l); + if (lnptr == NULL) { +#ifdef BOS + breakpoint(); +#endif + return -1; + } + + CKMAGIC(lnptr); + + lnptr->data = data_ptr; + + if (ln==l->top) { + /*------------------------------ + | insert before the list head + ------------------------------*/ + lnptr->next = ln; + lnptr->prev = NULL; + ln->prev = lnptr; + l->top = lnptr; + } + else if (ln==NULL) { + /*----------------- + | list was empty + -----------------*/ + lnptr->next = NULL; + lnptr->prev = l->bottom; + l->bottom->next = lnptr; + l->bottom = lnptr; + } + else { + /*----------------------------------- + | insert in the middle of the list + -----------------------------------*/ + lnptr->next = ln; + lnptr->prev = ln->prev; + lnptr->next->prev = lnptr; + lnptr->prev->next = lnptr; + } + + l->num++; + + CKLMAGIC(l); + + return 0; +} + + + +/*----------------------------------------------------------------- +| lins_n +| +| Insert data before the nth item in the list. + -----------------------------------------------------------------*/ +int +lins_n ( LISTID lid, void * data_ptr, unsigned int n ) +{ + int i; + LIST * l; + LISTNODE * ln; + + l = (LIST *)lid; + + CKLMAGIC(l); + + if ((n<1)||(n>(l->num+1))) { + return -1; + } + + if (l->num == 0) { + return ladd ( lid, data_ptr ); + } + + /*---------------------------------- + | locate the nth item in the list + ----------------------------------*/ + ln = l->top; + i = 1; + while (ln && (i!=n)) { + CKMAGIC(ln); + ln = ln->next; + i++; + } + + if (!ln) { + CKLMAGIC(l); + return -1; + } + + CKLMAGIC(l); + + /*----------------------------------------- + | insert before the nth item in the list + -----------------------------------------*/ + return insert_ln ( l, ln, data_ptr ); +} + + +/*----------------------------------------------------------------- +| lins_ln +| +| Insert data before the list node pointed to by ln. + -----------------------------------------------------------------*/ +int +lins_ln ( LISTID lid, LNODEID lnid, void * data_ptr ) +{ + LIST * l; + LISTNODE * ln; + LISTNODE * ln_ptr; + + l = (LIST *)lid; + ln = (LISTNODE *)lnid; + + CKLMAGIC(l); + + CKMAGIC(ln); + + /*----------------------------------------- + | validate that ln is indeed in the list + -----------------------------------------*/ + ln_ptr = l->top; + while ((ln_ptr!=NULL)&&(ln_ptr!=ln)) { + CKMAGIC(ln_ptr); + ln_ptr = ln_ptr->next; + } + + if (ln_ptr == NULL) { + CKLMAGIC(l); + return -1; + } + + CKLMAGIC(l); + + /*-------------------------------- + | insert the data into the list + --------------------------------*/ + return insert_ln ( l, ln, data_ptr ); +} + + + +/*---------------------------------------------------------------------- +| remove_ln +| +| Remove the item in the list pointed to by ln. This routine is not +| intended to be called directly by the user because the validity +| of ln is not checked. This routine is called by list manipulation +| routines within this module, in which ln is known to point to a +| valid list node. + ----------------------------------------------------------------------*/ +static +void * +remove_ln ( LIST * l, LISTNODE * ln ) +{ + void * r; + + CKLMAGIC(l); + + CKMAGIC(ln); + + if (ln==l->top) { + /*------------------------------ + | remove the head of the list + ------------------------------*/ + l->top = ln->next; + if (l->top != NULL) { + l->top->prev = NULL; + } + else { + /*---------------------------------------- + | this was the only item in the list + ----------------------------------------*/ + l->bottom = NULL; + } + } + else if (ln==l->bottom) { + /*------------------------------ + | remove the tail of the list + ------------------------------*/ + l->bottom = ln->prev; + if (l->bottom != NULL) { + l->bottom->next = NULL; + } + } + else { + /*------------------------------------- + | remove from the middle of the list + -------------------------------------*/ + ln->prev->next = ln->next; + ln->next->prev = ln->prev; + } + + /*----------------------------- + | prepare to return the data + -----------------------------*/ + r = ln->data; + + /*----------------------------------------------- + | free the listnode for re-use + -----------------------------------------------*/ + free_listnode(l,ln); + + /*------------------------------------ + | adjust the item count of the list + ------------------------------------*/ + l->num--; + + CKLMAGIC(l); + + return r; +} + + + +/*------------------------------------------------------------------------- +| lrmv_d +| +| remove from list, data - removes the data element from the list, +| destructive + -------------------------------------------------------------------------*/ +void * +lrmv_d ( LISTID lid, void * data_ptr ) +{ + LIST * l; + LISTNODE * ln; + int i; + + l = (LIST *)lid; + + CKLMAGIC(l); + + i = 0; + ln = l->top; + while (ln && (ln->data != data_ptr)) { + i++; + CKMAGIC(ln); + ln = ln->next; + } + + if (ln == NULL) { + CKLMAGIC(l); + return NULL; + } + else { + CKLMAGIC(l); + return remove_ln ( l, ln ); + } +} + + + +/*------------------------------------------------------------------------- +| lrmv_ln +| +| remove from list, by list node - remove the data element pointed to +| by 'ln' from the list, destructive + -------------------------------------------------------------------------*/ +void * +lrmv_ln ( LISTID lid, LNODEID lnid ) +{ + LIST * l; + LISTNODE * ln; + LISTNODE * p; + + l = (LIST *)lid; + ln = (LISTNODE *)lnid; + + CKLMAGIC(l); + + CKMAGIC(ln); + + p = l->top; + while ((p!=NULL)&&(p!=ln)) { + CKMAGIC(p); + p = p->next; + } + + if (p==NULL) { + CKLMAGIC(l); + return NULL; + } + else { + CKLMAGIC(l); + return remove_ln ( l, p ); + } +} + + + +/*---------------------------------------------------------------------- +| lrmv_n +| +| remove from list, by item number - remove the nth element from +| the list. + ----------------------------------------------------------------------*/ +void * +lrmv_n ( LISTID lid, unsigned int n ) +{ + int i; + LIST * l; + LISTNODE * ln; + + l = (LIST *)lid; + + CKLMAGIC(l); + + if ((n<1)||(n>l->num)) { + return NULL; + } + + ln = l->top; + i = 1; + while (ln && (i!=n)) { + CKMAGIC(ln); + ln = ln->next; + i++; + } + + if (ln) { + CKLMAGIC(l); + return remove_ln ( l, ln ); + } + else { + CKLMAGIC(l); + return NULL; + } +} + + +/*---------------------------------------------------------------------- +| lrmv +| +| remove from list, last item - remove the last item from the list, +| destructive + ----------------------------------------------------------------------*/ +void * +lrmv ( LISTID lid ) +{ + LIST * l; + LISTNODE * p; + + l = (LIST *)lid; + + CKLMAGIC(l); + + p = l->bottom; + + if (p == NULL) { + CKLMAGIC(l); + return NULL; + } + else { + CKLMAGIC(l); + return remove_ln ( l, p ); + } +} + + + +/*---------------------------------------------------------------------- +| lsrch +| +| search list - return data element pointed to by 'p', NULL if not +| found + ----------------------------------------------------------------------*/ +void * +lsrch ( LISTID lid, void * p, int (* compare)(void * p1, void * p2) ) +{ + LIST * l; + LISTNODE * ln; + + l = (LIST *)lid; + + CKLMAGIC(l); + + ln = l->top; + + while (ln!=NULL) { + CKMAGIC(ln); + if (compare(p,ln->data) == 0) { + CKLMAGIC(l); + return ln->data; + } + else { + ln = ln->next; + } + } + + CKLMAGIC(l); + return NULL; +} + + +int lprint ( FILE * f, LISTID lid ) +{ + LIST * l; + LISTNODE * ln; + NODEPOOL * np; + int count; + + l = (LIST *)lid; + + fprintf ( f, "list id %p internal data structures:\n", + lid ); +#if CHECK_MAGIC + if ((l->magic1 != MAGIC) || (l->magic2 != MAGIC)) { + fprintf ( f, " *** WARNING: LIST MAGIC IS CORRUPT ***\n" ); + } + fprintf ( f, + " magic1=0x%08x\n" + " magic2=0x%08x\n", + l->magic1, l->magic2 ); +#endif + fprintf ( f, " num f pool n_ln top bottom next_ln np_top np_bottom\n" ); + fprintf ( f, " ---- - ---- ---- ---------- ---------- ---------- ---------- ----------\n" ); + fprintf ( f, " %4d %1d %4d %4d %10p %10p %10p %10p %10p\n", + l->num, l->free_on_close, l->poolsize, l->n_ln_pool, + l->top, l->bottom, + l->next_ln, l->np_top, l->np_bottom ); + + + fprintf ( f, + " node pools:\n" + " idx np magic1 next prev magic2\n" + " ---- ---------- ---------- ---------- ---------- ----------\n" ); + count = 0; + np = l->np_top; + while (np != NULL) { + count++; + fprintf ( f, " %4d %10p 0x%08x %10p %10p 0x%08x\n", + count, np, +#if CHECK_MAGIC + np->magic1, +#else + 0, +#endif + np->chain_next, np->chain_prev, +#if CHECK_MAGIC + np->magic2 +#else + 0 +#endif + ); + np = np->chain_next; + } + + if (f) { + fprintf ( f, + " list elements:\n" + " n ln magic1 next prev data magic2\n" + " ---- ---------- ---------- ---------- ---------- ---------- ----------\n" ); + count = 0; + ln = l->top; + while (ln != NULL) { + count++; + fprintf ( f, " %4d %10p %10x %10p %10p %10p %10x\n", + count, ln, +#if CHECK_MAGIC + ln->magic1, +#else + 0, +#endif + ln->next, ln->prev, ln->data, +#if CHECK_MAGIC + ln->magic2 +#else + 0 +#endif + ); + ln = lnext(ln); + } + if (count != l->num) { + fprintf ( f, + " *** list count is not correct\n" + " *** list id indicates %d, counted items = %d\n", + l->num, count ); + } + } + + return 0; +} diff --git a/avrdude/lists.h b/avrdude/lists.h new file mode 100644 index 00000000..bae43ffd --- /dev/null +++ b/avrdude/lists.h @@ -0,0 +1,115 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 1990-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/*---------------------------------------------------------------------- + Id: lists.h,v 1.2 2001/08/19 23:13:17 bsd Exp $ + ----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + General purpose linked list routines - header file declarations. + + Author : Brian Dean + Date : 10 January, 1990 + ----------------------------------------------------------------------*/ +#ifndef lists_h +#define lists_h + +#include + +typedef void * LISTID; +typedef void * LNODEID; + + +/*---------------------------------------------------------------------- + several defines to access the LIST structure as as stack or a queue + --- use for program readability + ----------------------------------------------------------------------*/ +#define STACKID LISTID +#define SNODEID LNODEID +#define QUEUEID LISTID +#define QNODEID LNODEID + + +#define PUSH(s,d) lins_n(s,d,1) /* push 'd' onto the stack */ +#define POP(s) lrmv_n(s,1) /* pop the stack */ +#define LOOKSTACK(s) lget_n(s,1) /* look at the top of the stack, + but don't pop */ + + +#define ENQUEUE(q,d) lins_n(q,d,1) /* put 'd' on the end of the queue */ +#define DEQUEUE(q) lrmv(q) /* remove next item from the front of + the queue */ +#define REQUEUE(q,d) ladd(q,d) /* re-insert (push) item back on the + front of the queue */ +#define LOOKQUEUE(q) lget(q) /* return next item on the queue, + but don't dequeue */ +#define QUEUELEN(q) lsize(q) /* length of the queue */ + + +#define LISTADD(l,d) ladd(l,d) /* add to end of the list */ +#define LISTRMV(l,d) lrmv_d(l,d) /* remove from end of the list */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* .................... Function Prototypes .................... */ + +LISTID lcreat ( void * liststruct, int poolsize ); +void ldestroy ( LISTID lid ); +void ldestroy_cb ( LISTID lid, void (*ucleanup)() ); + +LNODEID lfirst ( LISTID ); /* head of the list */ +LNODEID llast ( LISTID ); /* tail of the list */ +LNODEID lnext ( LNODEID ); /* next item in the list */ +LNODEID lprev ( LNODEID ); /* previous item in the list */ +void * ldata ( LNODEID ); /* data at the current position */ +int lsize ( LISTID ); /* number of elements in the list */ + +int ladd ( LISTID lid, void * p ); +int laddo ( LISTID lid, void *p, + int (*compare)(const void *p1,const void *p2), + LNODEID * firstdup ); +int laddu ( LISTID lid, void * p, + int (*compare)(const void *p1,const void *p2)); +int lins_n ( LISTID lid, void * d, unsigned int n ); +int lins_ln ( LISTID lid, LNODEID lnid, void * data_ptr ); + +void * lget ( LISTID lid ); +void * lget_n ( LISTID lid, unsigned int n ); +LNODEID lget_ln ( LISTID lid, unsigned int n ); + +void * lrmv ( LISTID lid ); +void * lrmv_n ( LISTID lid, unsigned int n ); +void * lrmv_ln ( LISTID lid, LNODEID lnid ); +void * lrmv_d ( LISTID lid, void * data_ptr ); + +LISTID lcat ( LISTID lid1, LISTID lid2 ); + +void * lsrch ( LISTID lid, void * p, int (*compare)(void *p1,void *p2)); + +int lprint ( FILE * f, LISTID lid ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/main.c b/avrdude/main.c new file mode 100644 index 00000000..13c7fa48 --- /dev/null +++ b/avrdude/main.c @@ -0,0 +1,1269 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2005 Brian S. Dean + * Copyright 2007-2009 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Code to program an Atmel AVR device through one of the supported + * programmers. + * + * For parallel port connected programmers, the pin definitions can be + * changed via a config file. See the config file for instructions on + * how to add a programmer definition. + * + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "avr.h" +#include "config.h" +#include "confwin.h" +#include "fileio.h" +#include "lists.h" +#include "par.h" +#include "pindefs.h" +#include "term.h" +#include "safemode.h" +#include "update.h" + + +/* Get VERSION from ac_cfg.h */ +char * version = VERSION; + +char * progname; +char progbuf[PATH_MAX]; /* temporary buffer of spaces the same + length as progname; used for lining up + multiline messages */ + +struct list_walk_cookie +{ + FILE *f; + const char *prefix; +}; + +static LISTID updates; + +static LISTID extended_params; + +static PROGRAMMER * pgm; + +/* + * global options + */ +int do_cycles; /* track erase-rewrite cycles */ +int verbose; /* verbose output */ +int quell_progress; /* un-verebose output */ +int ovsigck; /* 1=override sig check, 0=don't */ + + +/* + * usage message + */ +static void usage(void) +{ + fprintf(stderr, + "Usage: %s [options]\n" + "Options:\n" + " -p Required. Specify AVR device.\n" + " -b Override RS-232 baud rate.\n" + " -B Specify JTAG/STK500v2 bit clock period (us).\n" + " -C Specify location of configuration file.\n" + " -c Specify programmer type.\n" + " -D Disable auto erase for flash memory\n" + " -i ISP Clock Delay [in microseconds]\n" + " -P Specify connection port.\n" + " -F Override invalid signature check.\n" + " -e Perform a chip erase.\n" + " -O Perform RC oscillator calibration (see AVR053). \n" + " -U :r|w|v:[:format]\n" + " Memory operation specification.\n" + " Multiple -U options are allowed, each request\n" + " is performed in the order specified.\n" + " -n Do not write anything to the device.\n" + " -V Do not verify.\n" + " -u Disable safemode, default when running from a script.\n" + " -s Silent safemode operation, will not ask you if\n" + " fuses should be changed back.\n" + " -t Enter terminal mode.\n" + " -E [,] List programmer exit specifications.\n" + " -x Pass to programmer.\n" + " -y Count # erase cycles in EEPROM.\n" + " -Y Initialize erase cycle # in EEPROM.\n" + " -v Verbose output. -v -v for more.\n" + " -q Quell progress output. -q -q for less.\n" + " -? Display this usage.\n" + "\navrdude version %s, URL: \n" + ,progname, version); +} + + +static void update_progress_tty (int percent, double etime, char *hdr) +{ + static char hashes[51]; + static char *header; + static int last = 0; + int i; + + setvbuf(stderr, (char*)NULL, _IONBF, 0); + + hashes[50] = 0; + + memset (hashes, ' ', 50); + for (i=0; i>1)*2; + + setvbuf(stderr, (char*)NULL, _IONBF, 0); + + if (hdr) { + fprintf (stderr, "\n%s | ", hdr); + last = 0; + done = 0; + } + else { + while ((cnt > last) && (done == 0)) { + fprintf (stderr, "#"); + cnt -= 2; + } + } + + if ((percent == 100) && (done == 0)) { + fprintf (stderr, " | 100%% %0.2fs\n\n", etime); + last = 0; + done = 1; + } + else + last = (percent>>1)*2; /* Make last a multiple of 2. */ + + setvbuf(stderr, (char*)NULL, _IOLBF, 0); +} + +static void list_programmers_callback(const char *name, const char *desc, + const char *cfgname, int cfglineno, + void *cookie) +{ + struct list_walk_cookie *c = (struct list_walk_cookie *)cookie; + + fprintf(c->f, "%s%-8s = %-30s [%s:%d]\n", + c->prefix, name, desc, cfgname, cfglineno); +} + +static void list_programmers(FILE * f, const char *prefix, LISTID programmers) +{ + struct list_walk_cookie c; + + c.f = f; + c.prefix = prefix; + + walk_programmers(programmers, list_programmers_callback, &c); +} + +static void list_avrparts_callback(const char *name, const char *desc, + const char *cfgname, int cfglineno, + void *cookie) +{ + struct list_walk_cookie *c = (struct list_walk_cookie *)cookie; + + fprintf(c->f, "%s%-4s = %-15s [%s:%d]\n", + c->prefix, name, desc, cfgname, cfglineno); +} + +static void list_parts(FILE * f, const char *prefix, LISTID avrparts) +{ + struct list_walk_cookie c; + + c.f = f; + c.prefix = prefix; + + walk_avrparts(avrparts, list_avrparts_callback, &c); +} + +static void exithook(void) +{ + if (pgm->teardown) + pgm->teardown(pgm); +} + +/* + * main routine + */ +int main(int argc, char * argv []) +{ + int rc; /* general return code checking */ + int exitrc; /* exit code for main() */ + int i; /* general loop counter */ + int ch; /* options flag */ + int len; /* length for various strings */ + struct avrpart * p; /* which avr part we are programming */ + struct avrpart * v; /* used for verify */ + AVRMEM * sig; /* signature data */ + struct stat sb; + UPDATE * upd; + LNODEID * ln; + + + /* options / operating mode variables */ + int erase; /* 1=erase chip, 0=don't */ + int calibrate; /* 1=calibrate RC oscillator, 0=don't */ + int auto_erase; /* 0=never erase unless explicity told to do + so, 1=erase if we are going to program flash */ + char * port; /* device port (/dev/xxx) */ + int terminal; /* 1=enter terminal mode, 0=don't */ + int nowrite; /* don't actually write anything to the chip */ + int verify; /* perform a verify operation */ + char * exitspecs; /* exit specs string from command line */ + char * programmer; /* programmer id */ + char * partdesc; /* part id */ + char sys_config[PATH_MAX]; /* system wide config file */ + char usr_config[PATH_MAX]; /* per-user config file */ + int cycles; /* erase-rewrite cycles */ + int set_cycles; /* value to set the erase-rewrite cycles to */ + char * e; /* for strtol() error checking */ + int baudrate; /* override default programmer baud rate */ + double bitclock; /* Specify programmer bit clock (JTAG ICE) */ + int ispdelay; /* Specify the delay for ISP clock */ + int safemode; /* Enable safemode, 1=safemode on, 0=normal */ + int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */ + int init_ok; /* Device initialization worked well */ + int is_open; /* Device open succeeded */ + unsigned char safemode_lfuse = 0xff; + unsigned char safemode_hfuse = 0xff; + unsigned char safemode_efuse = 0xff; + unsigned char safemode_fuse = 0xff; + + char * safemode_response; + int fuses_specified = 0; + int fuses_updated = 0; +#if !defined(WIN32NATIVE) + char * homedir; +#endif + + /* + * Set line buffering for file descriptors so we see stdout and stderr + * properly interleaved. + */ + setvbuf(stdout, (char*)NULL, _IOLBF, 0); + setvbuf(stderr, (char*)NULL, _IOLBF, 0); + + progname = strrchr(argv[0],'/'); + +#if defined (WIN32NATIVE) + /* take care of backslash as dir sep in W32 */ + if (!progname) progname = strrchr(argv[0],'\\'); +#endif /* WIN32NATIVE */ + + if (progname) + progname++; + else + progname = argv[0]; + + default_parallel[0] = 0; + default_serial[0] = 0; + default_bitclock = 0.0; + + init_config(); + + updates = lcreat(NULL, 0); + if (updates == NULL) { + fprintf(stderr, "%s: cannot initialize updater list\n", progname); + exit(1); + } + + extended_params = lcreat(NULL, 0); + if (extended_params == NULL) { + fprintf(stderr, "%s: cannot initialize extended parameter list\n", progname); + exit(1); + } + + partdesc = NULL; + port = default_parallel; + erase = 0; + calibrate = 0; + auto_erase = 1; + p = NULL; + ovsigck = 0; + terminal = 0; + nowrite = 0; + verify = 1; /* on by default */ + quell_progress = 0; + exitspecs = NULL; + pgm = NULL; + programmer = default_programmer; + verbose = 0; + do_cycles = 0; + set_cycles = -1; + baudrate = 0; + bitclock = 0.0; + ispdelay = 0; + safemode = 1; /* Safemode on by default */ + silentsafe = 0; /* Ask by default */ + is_open = 0; + + if (isatty(STDIN_FILENO) == 0) + safemode = 0; /* Turn off safemode if this isn't a terminal */ + + + +#if defined(WIN32NATIVE) + + win_sys_config_set(sys_config); + win_usr_config_set(usr_config); + +#else + + strcpy(sys_config, CONFIG_DIR); + i = strlen(sys_config); + if (i && (sys_config[i-1] != '/')) + strcat(sys_config, "/"); + strcat(sys_config, "avrdude.conf"); + + usr_config[0] = 0; + homedir = getenv("HOME"); + if (homedir != NULL) { + strcpy(usr_config, homedir); + i = strlen(usr_config); + if (i && (usr_config[i-1] != '/')) + strcat(usr_config, "/"); + strcat(usr_config, ".avrduderc"); + } + +#endif + + len = strlen(progname) + 2; + for (i=0; iop == DEVICE_WRITE) { + upd = dup_update(upd); + upd->op = DEVICE_VERIFY; + ladd(updates, upd); + } + break; + + case 'v': + verbose++; + break; + + case 'V': + verify = 0; + break; + + case 'x': + ladd(extended_params, optarg); + break; + + case 'y': + do_cycles = 1; + break; + + case 'Y': + set_cycles = strtol(optarg, &e, 0); + if ((e == optarg) || (*e != 0)) { + fprintf(stderr, "%s: invalid cycle count '%s'\n", + progname, optarg); + exit(1); + } + do_cycles = 1; + break; + + case '?': /* help */ + usage(); + exit(0); + break; + + default: + fprintf(stderr, "%s: invalid option -%c\n\n", progname, ch); + usage(); + exit(1); + break; + } + + } + + + if (quell_progress == 0) { + if (isatty (STDERR_FILENO)) + update_progress = update_progress_tty; + else { + update_progress = update_progress_no_tty; + /* disable all buffering of stderr for compatibility with + software that captures and redirects output to a GUI + i.e. Programmers Notepad */ + setvbuf( stderr, NULL, _IONBF, 0 ); + setvbuf( stdout, NULL, _IONBF, 0 ); + } + } + + if (verbose) { + /* + * Print out an identifying string so folks can tell what version + * they are running + */ + fprintf(stderr, + "\n%s: Version %s, compiled on %s at %s\n" + "%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n" + "%sCopyright (c) 2007-2009 Joerg Wunsch\n\n", + progname, version, __DATE__, __TIME__, progbuf, progbuf); + } + + if (verbose) { + fprintf(stderr, "%sSystem wide configuration file is \"%s\"\n", + progbuf, sys_config); + } + + rc = read_config(sys_config); + if (rc) { + fprintf(stderr, + "%s: error reading system wide configuration file \"%s\"\n", + progname, sys_config); + exit(1); + } + + if (usr_config[0] != 0) { + if (verbose) { + fprintf(stderr, "%sUser configuration file is \"%s\"\n", + progbuf, usr_config); + } + + rc = stat(usr_config, &sb); + if ((rc < 0) || ((sb.st_mode & S_IFREG) == 0)) { + if (verbose) { + fprintf(stderr, + "%sUser configuration file does not exist or is not a " + "regular file, skipping\n", + progbuf); + } + } + else { + rc = read_config(usr_config); + if (rc) { + fprintf(stderr, "%s: error reading user configuration file \"%s\"\n", + progname, usr_config); + exit(1); + } + } + } + // set bitclock from configuration files unless changed by command line + if (default_bitclock > 0 && bitclock == 0.0) { + bitclock = default_bitclock; + } + + if (verbose) { + fprintf(stderr, "\n"); + } + + if (partdesc) { + if (strcmp(partdesc, "?") == 0) { + fprintf(stderr, "\n"); + fprintf(stderr,"Valid parts are:\n"); + list_parts(stderr, " ", part_list); + fprintf(stderr, "\n"); + exit(1); + } + } + + if (programmer) { + if (strcmp(programmer, "?") == 0) { + fprintf(stderr, "\n"); + fprintf(stderr,"Valid programmers are:\n"); + list_programmers(stderr, " ", programmers); + fprintf(stderr,"\n"); + exit(1); + } + } + + + if (programmer[0] == 0) { + fprintf(stderr, + "\n%s: no programmer has been specified on the command line " + "or the config file\n", + progname); + fprintf(stderr, + "%sSpecify a programmer using the -c option and try again\n\n", + progbuf); + exit(1); + } + + pgm = locate_programmer(programmers, programmer); + if (pgm == NULL) { + fprintf(stderr,"\n"); + fprintf(stderr, + "%s: Can't find programmer id \"%s\"\n", + progname, programmer); + fprintf(stderr,"\nValid programmers are:\n"); + list_programmers(stderr, " ", programmers); + fprintf(stderr,"\n"); + exit(1); + } + + if (pgm->setup) { + pgm->setup(pgm); + } + if (pgm->teardown) { + atexit(exithook); + } + + if (lsize(extended_params) > 0) { + if (pgm->parseextparams == NULL) { + fprintf(stderr, + "%s: WARNING: Programmer doesn't support extended parameters," + " -x option(s) ignored\n", + progname); + } else { + if (pgm->parseextparams(pgm, extended_params) < 0) { + fprintf(stderr, + "%s: Error parsing extended parameter list\n", + progname); + exit(1); + } + } + } + + if ((strcmp(pgm->type, "STK500") == 0) || + (strcmp(pgm->type, "avr910") == 0) || + (strcmp(pgm->type, "BusPirate") == 0) || + (strcmp(pgm->type, "STK500V2") == 0) || + (strcmp(pgm->type, "JTAGMKII") == 0)) { + if (port == default_parallel) { + port = default_serial; + } + } + + if (partdesc == NULL) { + fprintf(stderr, + "%s: No AVR part has been specified, use \"-p Part\"\n\n", + progname); + fprintf(stderr,"Valid parts are:\n"); + list_parts(stderr, " ", part_list); + fprintf(stderr, "\n"); + exit(1); + } + + + p = locate_part(part_list, partdesc); + if (p == NULL) { + fprintf(stderr, + "%s: AVR Part \"%s\" not found.\n\n", + progname, partdesc); + fprintf(stderr,"Valid parts are:\n"); + list_parts(stderr, " ", part_list); + fprintf(stderr, "\n"); + exit(1); + } + + + if (exitspecs != NULL) { + if (pgm->parseexitspecs == NULL) { + fprintf(stderr, + "%s: WARNING: -E option not supported by this programmer type\n", + progname); + exitspecs = NULL; + } + else if (pgm->parseexitspecs(pgm, exitspecs) < 0) { + usage(); + exit(1); + } + } + + if(p->flags & AVRPART_AVR32) { + safemode = 0; + auto_erase = 0; + } + + if(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) { + safemode = 0; + } + + /* + * set up seperate instances of the avr part, one for use in + * programming, one for use in verifying. These are separate + * because they need separate flash and eeprom buffer space + */ + p = avr_dup_part(p); + v = avr_dup_part(p); + + /* + * open the programmer + */ + if (port[0] == 0) { + fprintf(stderr, "\n%s: no port has been specified on the command line " + "or the config file\n", + progname); + fprintf(stderr, "%sSpecify a port using the -P option and try again\n\n", + progbuf); + exit(1); + } + + if (verbose) { + fprintf(stderr, "%sUsing Port : %s\n", progbuf, port); + fprintf(stderr, "%sUsing Programmer : %s\n", progbuf, programmer); + if ((strcmp(pgm->type, "avr910") == 0)) { + fprintf(stderr, "%savr910_devcode (avrdude.conf) : ", progbuf); + if(p->avr910_devcode)fprintf(stderr, "0x%x\n", p->avr910_devcode); + else fprintf(stderr, "none\n"); + } + } + + if (baudrate != 0) { + if (verbose) { + fprintf(stderr, "%sOverriding Baud Rate : %d\n", progbuf, baudrate); + } + pgm->baudrate = baudrate; + } + + if (bitclock != 0.0) { + if (verbose) { + fprintf(stderr, "%sSetting bit clk period : %.1f\n", progbuf, bitclock); + } + pgm->bitclock = bitclock * 1e-6; + } + + if (ispdelay != 0) { + if (verbose) { + fprintf(stderr, "%sSetting isp clock delay : %3i\n", progbuf, ispdelay); + } + pgm->ispdelay = ispdelay; + } + + rc = pgm->open(pgm, port); + if (rc < 0) { + exitrc = 1; + pgm->ppidata = 0; /* clear all bits at exit */ + goto main_exit; + } + is_open = 1; + + if (calibrate) { + /* + * perform an RC oscillator calibration + * as outlined in appnote AVR053 + */ + if (pgm->perform_osccal == 0) { + fprintf(stderr, + "%s: programmer does not support RC oscillator calibration\n", + progname); + exitrc = 1; + } else { + fprintf(stderr, "%s: performing RC oscillator calibration\n", progname); + exitrc = pgm->perform_osccal(pgm); + } + if (exitrc == 0 && quell_progress < 2) { + fprintf(stderr, + "%s: calibration value is now stored in EEPROM at address 0\n", + progname); + } + goto main_exit; + } + + if (verbose) { + avr_display(stderr, p, progbuf, verbose); + fprintf(stderr, "\n"); + programmer_display(pgm, progbuf); + } + + if (quell_progress < 2) { + fprintf(stderr, "\n"); + } + + exitrc = 0; + + /* + * enable the programmer + */ + pgm->enable(pgm); + + /* + * turn off all the status leds + */ + pgm->rdy_led(pgm, OFF); + pgm->err_led(pgm, OFF); + pgm->pgm_led(pgm, OFF); + pgm->vfy_led(pgm, OFF); + + /* + * initialize the chip in preperation for accepting commands + */ + init_ok = (rc = pgm->initialize(pgm, p)) >= 0; + if (!init_ok) { + fprintf(stderr, "%s: initialization failed, rc=%d\n", progname, rc); + if (!ovsigck) { + fprintf(stderr, "%sDouble check connections and try again, " + "or use -F to override\n" + "%sthis check.\n\n", + progbuf, progbuf); + exitrc = 1; + goto main_exit; + } + } + + /* indicate ready */ + pgm->rdy_led(pgm, ON); + + if (quell_progress < 2) { + fprintf(stderr, + "%s: AVR device initialized and ready to accept instructions\n", + progname); + } + + /* + * Let's read the signature bytes to make sure there is at least a + * chip on the other end that is responding correctly. A check + * against 0xffffff / 0x000000 should ensure that the signature bytes + * are valid. + */ + if(!(p->flags & AVRPART_AVR32)) { + if (init_ok) { + rc = avr_signature(pgm, p); + if (rc != 0) { + fprintf(stderr, "%s: error reading signature data, rc=%d\n", + progname, rc); + exitrc = 1; + goto main_exit; + } + } + + sig = avr_locate_mem(p, "signature"); + if (sig == NULL) { + fprintf(stderr, + "%s: WARNING: signature data not defined for device \"%s\"\n", + progname, p->desc); + } + + if (sig != NULL) { + int ff, zz; + + if (quell_progress < 2) { + fprintf(stderr, "%s: Device signature = 0x", progname); + } + ff = zz = 1; + for (i=0; isize; i++) { + if (quell_progress < 2) { + fprintf(stderr, "%02x", sig->buf[i]); + } + if (sig->buf[i] != 0xff) + ff = 0; + if (sig->buf[i] != 0x00) + zz = 0; + } + if (quell_progress < 2) { + fprintf(stderr, "\n"); + } + + if (ff || zz) { + fprintf(stderr, + "%s: Yikes! Invalid device signature.\n", progname); + if (!ovsigck) { + fprintf(stderr, "%sDouble check connections and try again, " + "or use -F to override\n" + "%sthis check.\n\n", + progbuf, progbuf); + exitrc = 1; + goto main_exit; + } + } + } + + if (sig->size != 3 || + sig->buf[0] != p->signature[0] || + sig->buf[1] != p->signature[1] || + sig->buf[2] != p->signature[2]) { + fprintf(stderr, + "%s: Expected signature for %s is %02X %02X %02X\n", + progname, p->desc, + p->signature[0], p->signature[1], p->signature[2]); + if (!ovsigck) { + fprintf(stderr, "%sDouble check chip, " + "or use -F to override this check.\n", + progbuf); + exitrc = 1; + goto main_exit; + } + } + } + + if (init_ok && safemode == 1) { + /* If safemode is enabled, go ahead and read the current low, high, + and extended fuse bytes as needed */ + + rc = safemode_readfuses(&safemode_lfuse, &safemode_hfuse, + &safemode_efuse, &safemode_fuse, pgm, p, verbose); + + if (rc != 0) { + + //Check if the programmer just doesn't support reading + if (rc == -5) + { + if (verbose > 0) + { + fprintf(stderr, "%s: safemode: Fuse reading not support by programmer.\n" + " Safemode disabled.\n", progname); + } + safemode = 0; + } + else + { + + fprintf(stderr, "%s: safemode: To protect your AVR the programming " + "will be aborted\n", + progname); + exitrc = 1; + goto main_exit; + } + } else { + //Save the fuses as default + safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse); + } + } + + if ((erase == 0) && (auto_erase == 1)) { + AVRMEM * m; + for (ln=lfirst(updates); ln; ln=lnext(ln)) { + upd = ldata(ln); + m = avr_locate_mem(p, upd->memtype); + if (m == NULL) + continue; + if ((strcasecmp(m->desc, "flash") == 0) && (upd->op == DEVICE_WRITE)) { + erase = 1; + if (quell_progress < 2) { + fprintf(stderr, + "%s: NOTE: FLASH memory has been specified, an erase cycle " + "will be performed\n" + "%sTo disable this feature, specify the -D option.\n", + progname, progbuf); + } + break; + } + } + } + + /* + * Display cycle count, if and only if it is not set later on. + * + * The cycle count will be displayed anytime it will be changed later. + */ + if (init_ok && !(p->flags & AVRPART_AVR32) && + (set_cycles == -1) && ((erase == 0) || (do_cycles == 0))) { + /* + * see if the cycle count in the last four bytes of eeprom seems + * reasonable + */ + rc = avr_get_cycle_count(pgm, p, &cycles); + if (quell_progress < 2) { + if ((rc >= 0) && (cycles != 0)) { + fprintf(stderr, + "%s: current erase-rewrite cycle count is %d%s\n", + progname, cycles, + do_cycles ? "" : " (if being tracked)"); + } + } + } + + if (init_ok && set_cycles != -1 && !(p->flags & AVRPART_AVR32)) { + rc = avr_get_cycle_count(pgm, p, &cycles); + if (rc == 0) { + /* + * only attempt to update the cycle counter if we can actually + * read the old value + */ + cycles = set_cycles; + if (quell_progress < 2) { + fprintf(stderr, "%s: setting erase-rewrite cycle count to %d\n", + progname, cycles); + } + rc = avr_put_cycle_count(pgm, p, cycles); + if (rc < 0) { + fprintf(stderr, + "%s: WARNING: failed to update the erase-rewrite cycle " + "counter\n", + progname); + } + } + } + + if (init_ok && erase) { + /* + * erase the chip's flash and eeprom memories, this is required + * before the chip can accept new programming + */ + if (nowrite) { + fprintf(stderr, + "%s: conflicting -e and -n options specified, NOT erasing chip\n", + progname); + } else { + if (quell_progress < 2) { + fprintf(stderr, "%s: erasing chip\n", progname); + } + exitrc = avr_chip_erase(pgm, p); + if(exitrc) goto main_exit; + } + } + + if (terminal) { + /* + * terminal mode + */ + exitrc = terminal_mode(pgm, p); + } + + if (!init_ok) { + /* + * If we came here by the -tF options, bail out now. + */ + exitrc = 1; + goto main_exit; + } + + + for (ln=lfirst(updates); ln; ln=lnext(ln)) { + upd = ldata(ln); + rc = do_op(pgm, p, upd, nowrite, verify); + if (rc) { + exitrc = 1; + break; + } + } + + /* Right before we exit programming mode, which will make the fuse + bits active, check to make sure they are still correct */ + if (safemode == 1) { + /* If safemode is enabled, go ahead and read the current low, + * high, and extended fuse bytes as needed */ + unsigned char safemodeafter_lfuse = 0xff; + unsigned char safemodeafter_hfuse = 0xff; + unsigned char safemodeafter_efuse = 0xff; + unsigned char safemodeafter_fuse = 0xff; + unsigned char failures = 0; + char yes[1] = {'y'}; + + if (quell_progress < 2) { + fprintf(stderr, "\n"); + } + + //Restore the default fuse values + safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse); + + /* Try reading back fuses, make sure they are reliable to read back */ + if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse, + &safemodeafter_efuse, &safemodeafter_fuse, pgm, p, verbose) != 0) { + /* Uh-oh.. try once more to read back fuses */ + if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse, + &safemodeafter_efuse, &safemodeafter_fuse, pgm, p, verbose) != 0) { + fprintf(stderr, + "%s: safemode: Sorry, reading back fuses was unreliable. " + "I have given up and exited programming mode\n", + progname); + exitrc = 1; + goto main_exit; + } + } + + /* Now check what fuses are against what they should be */ + if (safemodeafter_fuse != safemode_fuse) { + fuses_updated = 1; + fprintf(stderr, "%s: safemode: fuse changed! Was %x, and is now %x\n", + progname, safemode_fuse, safemodeafter_fuse); + + + /* Ask user - should we change them */ + + if (silentsafe == 0) + safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] "); + else + safemode_response = yes; + + if (tolower((int)(safemode_response[0])) == 'y') { + + /* Enough chit-chat, time to program some fuses and check them */ + if (safemode_writefuse (safemode_fuse, "fuse", pgm, p, + 10, verbose) == 0) { + fprintf(stderr, "%s: safemode: and is now rescued\n", progname); + } + else { + fprintf(stderr, "%s: and COULD NOT be changed\n", progname); + failures++; + } + } + } + + /* Now check what fuses are against what they should be */ + if (safemodeafter_lfuse != safemode_lfuse) { + fuses_updated = 1; + fprintf(stderr, "%s: safemode: lfuse changed! Was %x, and is now %x\n", + progname, safemode_lfuse, safemodeafter_lfuse); + + + /* Ask user - should we change them */ + + if (silentsafe == 0) + safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] "); + else + safemode_response = yes; + + if (tolower((int)(safemode_response[0])) == 'y') { + + /* Enough chit-chat, time to program some fuses and check them */ + if (safemode_writefuse (safemode_lfuse, "lfuse", pgm, p, + 10, verbose) == 0) { + fprintf(stderr, "%s: safemode: and is now rescued\n", progname); + } + else { + fprintf(stderr, "%s: and COULD NOT be changed\n", progname); + failures++; + } + } + } + + /* Now check what fuses are against what they should be */ + if (safemodeafter_hfuse != safemode_hfuse) { + fuses_updated = 1; + fprintf(stderr, "%s: safemode: hfuse changed! Was %x, and is now %x\n", + progname, safemode_hfuse, safemodeafter_hfuse); + + /* Ask user - should we change them */ + if (silentsafe == 0) + safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] "); + else + safemode_response = yes; + if (tolower((int)(safemode_response[0])) == 'y') { + + /* Enough chit-chat, time to program some fuses and check them */ + if (safemode_writefuse(safemode_hfuse, "hfuse", pgm, p, + 10, verbose) == 0) { + fprintf(stderr, "%s: safemode: and is now rescued\n", progname); + } + else { + fprintf(stderr, "%s: and COULD NOT be changed\n", progname); + failures++; + } + } + } + + /* Now check what fuses are against what they should be */ + if (safemodeafter_efuse != safemode_efuse) { + fuses_updated = 1; + fprintf(stderr, "%s: safemode: efuse changed! Was %x, and is now %x\n", + progname, safemode_efuse, safemodeafter_efuse); + + /* Ask user - should we change them */ + if (silentsafe == 0) + safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] "); + else + safemode_response = yes; + if (tolower((int)(safemode_response[0])) == 'y') { + + /* Enough chit-chat, time to program some fuses and check them */ + if (safemode_writefuse (safemode_efuse, "efuse", pgm, p, + 10, verbose) == 0) { + fprintf(stderr, "%s: safemode: and is now rescued\n", progname); + } + else { + fprintf(stderr, "%s: and COULD NOT be changed\n", progname); + failures++; + } + } + } + + if (quell_progress < 2) { + fprintf(stderr, "%s: safemode: ", progname); + if (failures == 0) { + fprintf(stderr, "Fuses OK\n"); + } + else { + fprintf(stderr, "Fuses not recovered, sorry\n"); + } + } + + if (fuses_updated && fuses_specified) { + exitrc = 1; + } + + } + + +main_exit: + + /* + * program complete + */ + + if (is_open) { + pgm->powerdown(pgm); + + pgm->disable(pgm); + + pgm->rdy_led(pgm, OFF); + } + + pgm->close(pgm); + + if (quell_progress < 2) { + fprintf(stderr, "\n%s done. Thank you.\n\n", progname); + } + + return exitrc; +} diff --git a/avrdude/my_ddk_hidsdi.h b/avrdude/my_ddk_hidsdi.h new file mode 100644 index 00000000..99859d06 --- /dev/null +++ b/avrdude/my_ddk_hidsdi.h @@ -0,0 +1,49 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2006 Christian Starkjohann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* +The following is a replacement for hidsdi.h from the Windows DDK. It defines some +of the types and function prototypes of this header for our project. If you +have the Windows DDK version of this file or a version shipped with MinGW, use +that instead. +*/ +#ifndef MY_DDK_HIDSDI_H +#define MY_DDK_HIDSDI_H +#include +#include +#include +typedef struct{ + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; +}HIDD_ATTRIBUTES; +void __stdcall HidD_GetHidGuid(OUT LPGUID hidGuid); +BOOLEAN __stdcall HidD_GetAttributes(IN HANDLE device, OUT HIDD_ATTRIBUTES *attributes); +BOOLEAN __stdcall HidD_GetManufacturerString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen); +BOOLEAN __stdcall HidD_GetProductString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen); +BOOLEAN __stdcall HidD_GetSerialNumberString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen); +BOOLEAN __stdcall HidD_GetFeature(IN HANDLE device, OUT void *reportBuffer, IN ULONG bufferLen); +BOOLEAN __stdcall HidD_SetFeature(IN HANDLE device, IN void *reportBuffer, IN ULONG bufferLen); +BOOLEAN __stdcall HidD_GetNumInputBuffers(IN HANDLE device, OUT ULONG *numBuffers); +BOOLEAN __stdcall HidD_SetNumInputBuffers(IN HANDLE device, OUT ULONG numBuffers); +#include +#endif /* MY_DDK_HIDSDI_H */ diff --git a/avrdude/par.c b/avrdude/par.c new file mode 100644 index 00000000..54a04cf3 --- /dev/null +++ b/avrdude/par.c @@ -0,0 +1,462 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2006 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# include "freebsd_ppi.h" +#elif defined(__linux__) +# include "linux_ppdev.h" +#elif defined(__sun__) || defined(__sun) /* Solaris */ +# include "solaris_ecpp.h" +#endif + +#include "avrdude.h" +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" +#include "ppi.h" +#include "bitbang.h" + +#if HAVE_PARPORT + +struct ppipins_t { + int pin; + int reg; + int bit; + int inverted; +}; + +static struct ppipins_t ppipins[] = { + { 1, PPICTRL, 0x01, 1 }, + { 2, PPIDATA, 0x01, 0 }, + { 3, PPIDATA, 0x02, 0 }, + { 4, PPIDATA, 0x04, 0 }, + { 5, PPIDATA, 0x08, 0 }, + { 6, PPIDATA, 0x10, 0 }, + { 7, PPIDATA, 0x20, 0 }, + { 8, PPIDATA, 0x40, 0 }, + { 9, PPIDATA, 0x80, 0 }, + { 10, PPISTATUS, 0x40, 0 }, + { 11, PPISTATUS, 0x80, 1 }, + { 12, PPISTATUS, 0x20, 0 }, + { 13, PPISTATUS, 0x10, 0 }, + { 14, PPICTRL, 0x02, 1 }, + { 15, PPISTATUS, 0x08, 0 }, + { 16, PPICTRL, 0x04, 0 }, + { 17, PPICTRL, 0x08, 1 } +}; + +#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t)) + +static int par_setpin(PROGRAMMER * pgm, int pin, int value) +{ + int inverted; + + inverted = pin & PIN_INVERSE; + pin &= PIN_MASK; + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + if (ppipins[pin].inverted) + inverted = !inverted; + + if (inverted) + value = !value; + + if (value) + ppi_set(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + else + ppi_clr(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + + return 0; +} + +static void par_setmany(PROGRAMMER * pgm, unsigned int pinset, int value) +{ + int pin; + + for (pin = 1; pin <= 17; pin++) { + if (pinset & (1 << pin)) + par_setpin(pgm, pin, value); + } +} + +static int par_getpin(PROGRAMMER * pgm, int pin) +{ + int value; + int inverted; + + inverted = pin & PIN_INVERSE; + pin &= PIN_MASK; + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + value = ppi_get(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + + if (value) + value = 1; + + if (ppipins[pin].inverted) + inverted = !inverted; + + if (inverted) + value = !value; + + return value; +} + + +static int par_highpulsepin(PROGRAMMER * pgm, int pin) +{ + int inverted; + + inverted = pin & PIN_INVERSE; + pin &= PIN_MASK; + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + if (ppipins[pin].inverted) + inverted = !inverted; + + if (inverted) { + ppi_clr(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + + ppi_set(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + } else { + ppi_set(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + + ppi_clr(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit); + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + } + + return 0; +} + +static char * pins_to_str(unsigned int pmask) +{ + static char buf[64]; + int pin; + char b2[8]; + + buf[0] = 0; + for (pin = 1; pin <= 17; pin++) { + if (pmask & (1 << pin)) { + sprintf(b2, "%d", pin); + if (buf[0] != 0) + strcat(buf, ","); + strcat(buf, b2); + } + } + + return buf; +} + +/* + * apply power to the AVR processor + */ +static void par_powerup(PROGRAMMER * pgm) +{ + par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 1); /* power up */ + usleep(100000); +} + + +/* + * remove power from the AVR processor + */ +static void par_powerdown(PROGRAMMER * pgm) +{ + par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 0); /* power down */ +} + +static void par_disable(PROGRAMMER * pgm) +{ + par_setmany(pgm, pgm->pinno[PPI_AVR_BUFF], 1); /* turn off */ +} + +static void par_enable(PROGRAMMER * pgm) +{ + /* + * Prepare to start talking to the connected device - pull reset low + * first, delay a few milliseconds, then enable the buffer. This + * sequence allows the AVR to be reset before the buffer is enabled + * to avoid a short period of time where the AVR may be driving the + * programming lines at the same time the programmer tries to. Of + * course, if a buffer is being used, then the /RESET line from the + * programmer needs to be directly connected to the AVR /RESET line + * and not via the buffer chip. + */ + + par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0); + usleep(1); + + /* + * enable the 74367 buffer, if connected; this signal is active low + */ + par_setmany(pgm, pgm->pinno[PPI_AVR_BUFF], 0); +} + +static int par_open(PROGRAMMER * pgm, char * port) +{ + int rc; + + bitbang_check_prerequisites(pgm); + + ppi_open(port, &pgm->fd); + if (pgm->fd.ifd < 0) { + fprintf(stderr, "%s: failed to open parallel port \"%s\"\n\n", + progname, port); + exit(1); + } + + /* + * save pin values, so they can be restored when device is closed + */ + rc = ppi_getall(&pgm->fd, PPIDATA); + if (rc < 0) { + fprintf(stderr, "%s: error reading status of ppi data port\n", progname); + return -1; + } + pgm->ppidata = rc; + + rc = ppi_getall(&pgm->fd, PPICTRL); + if (rc < 0) { + fprintf(stderr, "%s: error reading status of ppi ctrl port\n", progname); + return -1; + } + pgm->ppictrl = rc; + + return 0; +} + + +static void par_close(PROGRAMMER * pgm) +{ + + /* + * Restore pin values before closing, + * but ensure that buffers are turned off. + */ + ppi_setall(&pgm->fd, PPIDATA, pgm->ppidata); + ppi_setall(&pgm->fd, PPICTRL, pgm->ppictrl); + + par_setmany(pgm, pgm->pinno[PPI_AVR_BUFF], 1); + + /* + * Handle exit specs. + */ + switch (pgm->exit_reset) { + case EXIT_RESET_ENABLED: + par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0); + break; + + case EXIT_RESET_DISABLED: + par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); + break; + + case EXIT_RESET_UNSPEC: + /* Leave it alone. */ + break; + } + + switch (pgm->exit_datahigh) { + case EXIT_DATAHIGH_ENABLED: + ppi_setall(&pgm->fd, PPIDATA, 0xff); + break; + + case EXIT_DATAHIGH_DISABLED: + ppi_setall(&pgm->fd, PPIDATA, 0x00); + break; + + case EXIT_DATAHIGH_UNSPEC: + /* Leave it alone. */ + break; + } + + switch (pgm->exit_vcc) { + case EXIT_VCC_ENABLED: + par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 1); + break; + + case EXIT_VCC_DISABLED: + par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 0); + break; + + case EXIT_VCC_UNSPEC: + /* Leave it alone. */ + break; + } + + ppi_close(&pgm->fd); + pgm->fd.ifd = -1; +} + +static void par_display(PROGRAMMER * pgm, const char * p) +{ + char vccpins[64]; + char buffpins[64]; + + if (pgm->pinno[PPI_AVR_VCC]) { + snprintf(vccpins, sizeof(vccpins), "%s", + pins_to_str(pgm->pinno[PPI_AVR_VCC])); + } + else { + strcpy(vccpins, " (not used)"); + } + + if (pgm->pinno[PPI_AVR_BUFF]) { + snprintf(buffpins, sizeof(buffpins), "%s", + pins_to_str(pgm->pinno[PPI_AVR_BUFF])); + } + else { + strcpy(buffpins, " (not used)"); + } + + fprintf(stderr, + "%s VCC = %s\n" + "%s BUFF = %s\n" + "%s RESET = %d\n" + "%s SCK = %d\n" + "%s MOSI = %d\n" + "%s MISO = %d\n" + "%s ERR LED = %d\n" + "%s RDY LED = %d\n" + "%s PGM LED = %d\n" + "%s VFY LED = %d\n", + + p, vccpins, + p, buffpins, + p, pgm->pinno[PIN_AVR_RESET], + p, pgm->pinno[PIN_AVR_SCK], + p, pgm->pinno[PIN_AVR_MOSI], + p, pgm->pinno[PIN_AVR_MISO], + p, pgm->pinno[PIN_LED_ERR], + p, pgm->pinno[PIN_LED_RDY], + p, pgm->pinno[PIN_LED_PGM], + p, pgm->pinno[PIN_LED_VFY]); +} + + +/* + * parse the -E string + */ +static int par_parseexitspecs(PROGRAMMER * pgm, char *s) +{ + char *cp; + + while ((cp = strtok(s, ","))) { + if (strcmp(cp, "reset") == 0) { + pgm->exit_reset = EXIT_RESET_ENABLED; + } + else if (strcmp(cp, "noreset") == 0) { + pgm->exit_reset = EXIT_RESET_DISABLED; + } + else if (strcmp(cp, "vcc") == 0) { + pgm->exit_vcc = EXIT_VCC_ENABLED; + } + else if (strcmp(cp, "novcc") == 0) { + pgm->exit_vcc = EXIT_VCC_DISABLED; + } + else if (strcmp(cp, "d_high") == 0) { + pgm->exit_datahigh = EXIT_DATAHIGH_ENABLED; + } + else if (strcmp(cp, "d_low") == 0) { + pgm->exit_datahigh = EXIT_DATAHIGH_DISABLED; + } + else { + return -1; + } + s = 0; /* strtok() should be called with the actual string only once */ + } + + return 0; +} + +void par_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "PPI"); + + pgm->exit_vcc = EXIT_VCC_UNSPEC; + pgm->exit_reset = EXIT_RESET_UNSPEC; + pgm->exit_datahigh = EXIT_DATAHIGH_UNSPEC; + + pgm->rdy_led = bitbang_rdy_led; + pgm->err_led = bitbang_err_led; + pgm->pgm_led = bitbang_pgm_led; + pgm->vfy_led = bitbang_vfy_led; + pgm->initialize = bitbang_initialize; + pgm->display = par_display; + pgm->enable = par_enable; + pgm->disable = par_disable; + pgm->powerup = par_powerup; + pgm->powerdown = par_powerdown; + pgm->program_enable = bitbang_program_enable; + pgm->chip_erase = bitbang_chip_erase; + pgm->cmd = bitbang_cmd; + pgm->cmd_tpi = bitbang_cmd_tpi; + pgm->spi = bitbang_spi; + pgm->open = par_open; + pgm->close = par_close; + pgm->setpin = par_setpin; + pgm->getpin = par_getpin; + pgm->highpulsepin = par_highpulsepin; + pgm->parseexitspecs = par_parseexitspecs; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; +} + +#else /* !HAVE_PARPORT */ + +void par_initpgm(PROGRAMMER * pgm) +{ + fprintf(stderr, + "%s: parallel port access not available in this configuration\n", + progname); +} + +#endif /* HAVE_PARPORT */ diff --git a/avrdude/par.h b/avrdude/par.h new file mode 100644 index 00000000..7d9b2416 --- /dev/null +++ b/avrdude/par.h @@ -0,0 +1,35 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef par_h +#define par_h + +#ifdef __cplusplus +extern "C" { +#endif + +void par_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/pgm.c b/avrdude/pgm.c new file mode 100644 index 00000000..6c80dac9 --- /dev/null +++ b/avrdude/pgm.c @@ -0,0 +1,228 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004 Brian S. Dean + * Copyright 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include + +#include "avrdude.h" +#include "pgm.h" + +static int pgm_default_2 (struct programmer_t *, AVRPART *); +static int pgm_default_3 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value); +static void pgm_default_4 (struct programmer_t *); +static int pgm_default_5 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data); +static void pgm_default_6 (struct programmer_t *, const char *); + + +static int pgm_default_open (struct programmer_t *pgm, char * name) +{ + fprintf (stderr, "\n%s: Fatal error: Programmer does not support open()", + progname); + exit(1); +} + +static int pgm_default_led (struct programmer_t * pgm, int value) +{ + /* + * If programmer has no LEDs, just do nothing. + */ + return 0; +} + + +static void pgm_default_powerup_powerdown (struct programmer_t * pgm) +{ + /* + * If programmer does not support powerup/down, just do nothing. + */ +} + + +PROGRAMMER * pgm_new(void) +{ + int i; + PROGRAMMER * pgm; + + pgm = (PROGRAMMER *)malloc(sizeof(*pgm)); + if (pgm == NULL) { + fprintf(stderr, "%s: out of memory allocating programmer structure\n", + progname); + exit(1); + } + + memset(pgm, 0, sizeof(*pgm)); + + pgm->id = lcreat(NULL, 0); + pgm->desc[0] = 0; + pgm->type[0] = 0; + pgm->config_file[0] = 0; + pgm->lineno = 0; + pgm->baudrate = 0; + + for (i=0; ipinno[i] = 0; + + /* + * mandatory functions - these are called without checking to see + * whether they are assigned or not + */ + pgm->initialize = pgm_default_2; + pgm->display = pgm_default_6; + pgm->enable = pgm_default_4; + pgm->disable = pgm_default_4; + pgm->powerup = pgm_default_powerup_powerdown; + pgm->powerdown = pgm_default_powerup_powerdown; + pgm->program_enable = pgm_default_2; + pgm->chip_erase = pgm_default_2; + pgm->open = pgm_default_open; + pgm->close = pgm_default_4; + pgm->read_byte = pgm_default_3; + pgm->write_byte = pgm_default_5; + + /* + * predefined functions - these functions have a valid default + * implementation. Hence, they don't need to be defined in + * the programmer. + */ + pgm->rdy_led = pgm_default_led; + pgm->err_led = pgm_default_led; + pgm->pgm_led = pgm_default_led; + pgm->vfy_led = pgm_default_led; + + /* + * optional functions - these are checked to make sure they are + * assigned before they are called + */ + pgm->cmd = NULL; + pgm->cmd_tpi = NULL; + pgm->spi = NULL; + pgm->paged_write = NULL; + pgm->paged_load = NULL; + pgm->write_setup = NULL; + pgm->read_sig_bytes = NULL; + pgm->set_vtarget = NULL; + pgm->set_varef = NULL; + pgm->set_fosc = NULL; + pgm->perform_osccal = NULL; + pgm->parseextparams = NULL; + pgm->setup = NULL; + pgm->teardown = NULL; + + return pgm; +} + + +static void pgm_default(void) +{ + fprintf(stderr, "%s: programmer operation not supported\n", progname); +} + + +static int pgm_default_2 (struct programmer_t * pgm, AVRPART * p) +{ + pgm_default(); + return -1; +} + +static int pgm_default_3 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + pgm_default(); + return -1; +} + +static void pgm_default_4 (struct programmer_t * pgm) +{ + pgm_default(); +} + +static int pgm_default_5 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + pgm_default(); + return -1; +} + +static void pgm_default_6 (struct programmer_t * pgm, const char * p) +{ + pgm_default(); +} + + +void programmer_display(PROGRAMMER * pgm, const char * p) +{ + fprintf(stderr, "%sProgrammer Type : %s\n", p, pgm->type); + fprintf(stderr, "%sDescription : %s\n", p, pgm->desc); + + pgm->display(pgm, p); +} + +PROGRAMMER * locate_programmer(LISTID programmers, const char * configid) +{ + LNODEID ln1, ln2; + PROGRAMMER * p = NULL; + const char * id; + int found; + + found = 0; + + for (ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) { + p = ldata(ln1); + for (ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) { + id = ldata(ln2); + if (strcasecmp(configid, id) == 0) + found = 1; + } + } + + if (found) + return p; + + return NULL; +} + +/* + * Iterate over the list of programmers given as "programmers", and + * call the callback function cb for each entry found. cb is being + * passed the following arguments: + * . the name of the programmer (for -c) + * . the descriptive text given in the config file + * . the name of the config file this programmer has been defined in + * . the line number of the config file this programmer has been defined at + * . the "cookie" passed into walk_programmers() (opaque client data) + */ +void walk_programmers(LISTID programmers, walk_programmers_cb cb, void *cookie) +{ + LNODEID ln1; + PROGRAMMER * p; + + for (ln1 = lfirst(programmers); ln1; ln1 = lnext(ln1)) { + p = ldata(ln1); + cb((char *)ldata(lfirst(p->id)), p->desc, p->config_file, p->lineno, cookie); + } +} + diff --git a/avrdude/pgm.h b/avrdude/pgm.h new file mode 100644 index 00000000..db4c6bc3 --- /dev/null +++ b/avrdude/pgm.h @@ -0,0 +1,145 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004 Brian S. Dean + * Copyright 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef pgm_h +#define pgm_h + +#include + +#include "avrpart.h" +#include "lists.h" +#include "pindefs.h" +#include "serial.h" + +#define ON 1 +#define OFF 0 + +#define PGM_DESCLEN 80 +#define PGM_PORTLEN PATH_MAX +#define PGM_TYPELEN 32 +#define PGM_USBSTRINGLEN 256 + +typedef enum { + EXIT_VCC_UNSPEC, + EXIT_VCC_ENABLED, + EXIT_VCC_DISABLED +} exit_vcc_t; + +typedef enum { + EXIT_RESET_UNSPEC, + EXIT_RESET_ENABLED, + EXIT_RESET_DISABLED +} exit_reset_t; + +typedef enum { + EXIT_DATAHIGH_UNSPEC, + EXIT_DATAHIGH_ENABLED, + EXIT_DATAHIGH_DISABLED +} exit_datahigh_t; + +typedef struct programmer_t { + LISTID id; + char desc[PGM_DESCLEN]; + char type[PGM_TYPELEN]; + char port[PGM_PORTLEN]; + unsigned int pinno[N_PINS]; + exit_vcc_t exit_vcc; + exit_reset_t exit_reset; + exit_datahigh_t exit_datahigh; + int ppidata; + int ppictrl; + int baudrate; + int usbvid, usbpid; + char usbdev[PGM_USBSTRINGLEN], usbsn[PGM_USBSTRINGLEN]; + char usbvendor[PGM_USBSTRINGLEN], usbproduct[PGM_USBSTRINGLEN]; + double bitclock; /* JTAG ICE clock period in microseconds */ + int ispdelay; /* ISP clock delay */ + union filedescriptor fd; + int page_size; /* page size if the programmer supports paged write/load */ + int (*rdy_led) (struct programmer_t * pgm, int value); + int (*err_led) (struct programmer_t * pgm, int value); + int (*pgm_led) (struct programmer_t * pgm, int value); + int (*vfy_led) (struct programmer_t * pgm, int value); + int (*initialize) (struct programmer_t * pgm, AVRPART * p); + void (*display) (struct programmer_t * pgm, const char * p); + void (*enable) (struct programmer_t * pgm); + void (*disable) (struct programmer_t * pgm); + void (*powerup) (struct programmer_t * pgm); + void (*powerdown) (struct programmer_t * pgm); + int (*program_enable) (struct programmer_t * pgm, AVRPART * p); + int (*chip_erase) (struct programmer_t * pgm, AVRPART * p); + int (*cmd) (struct programmer_t * pgm, unsigned char cmd[4], + unsigned char res[4]); + int (*cmd_tpi) (struct programmer_t * pgm, unsigned char cmd[], + int cmd_len, unsigned char res[], int res_len); + int (*spi) (struct programmer_t * pgm, unsigned char cmd[], + unsigned char res[], int count); + int (*open) (struct programmer_t * pgm, char * port); + void (*close) (struct programmer_t * pgm); + int (*paged_write) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes); + int (*paged_load) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes); + void (*write_setup) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m); + int (*write_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char value); + int (*read_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, + unsigned long addr, unsigned char * value); + int (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m); + void (*print_parms) (struct programmer_t * pgm); + int (*set_vtarget) (struct programmer_t * pgm, double v); + int (*set_varef) (struct programmer_t * pgm, unsigned int chan, double v); + int (*set_fosc) (struct programmer_t * pgm, double v); + int (*set_sck_period) (struct programmer_t * pgm, double v); + int (*setpin) (struct programmer_t * pgm, int pin, int value); + int (*getpin) (struct programmer_t * pgm, int pin); + int (*highpulsepin) (struct programmer_t * pgm, int pin); + int (*parseexitspecs) (struct programmer_t * pgm, char *s); + int (*perform_osccal) (struct programmer_t * pgm); + int (*parseextparams) (struct programmer_t * pgm, LISTID xparams); + void (*setup) (struct programmer_t * pgm); + void (*teardown) (struct programmer_t * pgm); + char config_file[PATH_MAX]; /* config file where defined */ + int lineno; /* config file line number */ + void *cookie; /* for private use by the programmer */ + char flag; /* for private use of the programmer */ +} PROGRAMMER; + +#ifdef __cplusplus +extern "C" { +#endif + +PROGRAMMER * pgm_new(void); + +void programmer_display(PROGRAMMER * pgm, const char * p); +PROGRAMMER * locate_programmer(LISTID programmers, const char * configid); + +typedef void (*walk_programmers_cb)(const char *name, const char *desc, + const char *cfgname, int cfglineno, + void *cookie); +void walk_programmers(LISTID programmers, walk_programmers_cb cb, void *cookie); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/pindefs.h b/avrdude/pindefs.h new file mode 100644 index 00000000..9c16ed1c --- /dev/null +++ b/avrdude/pindefs.h @@ -0,0 +1,44 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef __pindefs_h__ +#define __pindefs_h__ + +enum { + PPI_AVR_VCC=1, + PPI_AVR_BUFF, + PIN_AVR_RESET, + PIN_AVR_SCK, + PIN_AVR_MOSI, + PIN_AVR_MISO, + PIN_LED_ERR, + PIN_LED_RDY, + PIN_LED_PGM, + PIN_LED_VFY, + N_PINS +}; +#define PIN_INVERSE 0x80 /* flag for inverted pin in serbb */ +#define PIN_MASK 0x7f + +#define LED_ON(fd,pin) ppi_setpin(fd,pin,0) +#define LED_OFF(fd,pin) ppi_setpin(fd,pin,1) + +#endif diff --git a/avrdude/ppi.c b/avrdude/ppi.c new file mode 100644 index 00000000..423d5923 --- /dev/null +++ b/avrdude/ppi.c @@ -0,0 +1,238 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + + +#if !defined(WIN32NATIVE) + +#include "ac_cfg.h" + +#if HAVE_PARPORT + +#include +#include +#include +#include +#include +#include + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# include "freebsd_ppi.h" +#elif defined(__linux__) +# include "linux_ppdev.h" +#elif defined(__sun__) || defined(__sun) /* Solaris */ +# include "solaris_ecpp.h" +#endif + +#include "avrdude.h" +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" +#include "ppi.h" + +enum { + PPI_READ, + PPI_WRITE, + PPI_SHADOWREAD +}; + +static int ppi_shadow_access(union filedescriptor *fdp, int reg, + unsigned char *v, unsigned char action) +{ + static unsigned char shadow[3]; + int shadow_num; + + switch (reg) { + case PPIDATA: + shadow_num = 0; + break; + case PPICTRL: + shadow_num = 1; + break; + case PPISTATUS: + shadow_num = 2; + break; + default: + fprintf(stderr, "%s: avr_set(): invalid register=%d\n", + progname, reg); + return -1; + break; + } + + switch (action) { + case PPI_SHADOWREAD: + *v = shadow[shadow_num]; + break; + case PPI_READ: + DO_PPI_READ(fdp->ifd, reg, v); + shadow[shadow_num]=*v; + break; + case PPI_WRITE: + shadow[shadow_num]=*v; + DO_PPI_WRITE(fdp->ifd, reg, v); + break; + } + return 0; +} + +/* + * set the indicated bit of the specified register. + */ +int ppi_set(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + int rc; + + rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD); + v |= bit; + rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE); + + if (rc) + return -1; + + return 0; +} + + +/* + * clear the indicated bit of the specified register. + */ +int ppi_clr(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + int rc; + + rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD); + v &= ~bit; + rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE); + + if (rc) + return -1; + + return 0; +} + + +/* + * get the indicated bit of the specified register. + */ +int ppi_get(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + int rc; + + rc = ppi_shadow_access(fdp, reg, &v, PPI_READ); + v &= bit; + + if (rc) + return -1; + + return v; /* v == bit */ +} + +/* + * toggle the indicated bit of the specified register. + */ +int ppi_toggle(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + int rc; + + rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD); + v ^= bit; + rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE); + + if (rc) + return -1; + + return 0; +} + + +/* + * get all bits of the specified register. + */ +int ppi_getall(union filedescriptor *fdp, int reg) +{ + unsigned char v; + int rc; + + rc = ppi_shadow_access(fdp, reg, &v, PPI_READ); + + if (rc) + return -1; + + return v; /* v == bit */ +} + +/* + * set all bits of the specified register to val. + */ +int ppi_setall(union filedescriptor *fdp, int reg, int val) +{ + unsigned char v; + int rc; + + v = val; + rc = ppi_shadow_access(fdp, reg, &v, PPI_WRITE); + + if (rc) + return -1; + + return 0; +} + + +void ppi_open(char * port, union filedescriptor *fdp) +{ + int fd; + unsigned char v; + + fd = open(port, O_RDWR); + if (fd < 0) { + fprintf(stderr, "%s: can't open device \"%s\": %s\n", + progname, port, strerror(errno)); + fdp->ifd = -1; + return; + } + + ppi_claim (fd); + + /* + * Initialize shadow registers + */ + + ppi_shadow_access (fdp, PPIDATA, &v, PPI_READ); + ppi_shadow_access (fdp, PPICTRL, &v, PPI_READ); + ppi_shadow_access (fdp, PPISTATUS, &v, PPI_READ); + + fdp->ifd = fd; +} + + +void ppi_close(union filedescriptor *fdp) +{ + ppi_release (fdp->ifd); + close(fdp->ifd); +} + +#endif /* HAVE_PARPORT */ + +#endif /* !WIN32NATIVE */ diff --git a/avrdude/ppi.h b/avrdude/ppi.h new file mode 100644 index 00000000..f12b839b --- /dev/null +++ b/avrdude/ppi.h @@ -0,0 +1,60 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef ppi_h +#define ppi_h + +/* + * PPI registers + */ +enum { + PPIDATA, + PPICTRL, + PPISTATUS +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int ppi_get (union filedescriptor *fdp, int reg, int bit); + +int ppi_set (union filedescriptor *fdp, int reg, int bit); + +int ppi_clr (union filedescriptor *fdp, int reg, int bit); + +int ppi_getall (union filedescriptor *fdp, int reg); + +int ppi_setall (union filedescriptor *fdp, int reg, int val); + +int ppi_toggle (union filedescriptor *fdp, int reg, int bit); + +void ppi_open (char * port, union filedescriptor *fdp); + +void ppi_close (union filedescriptor *fdp); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/avrdude/ppiwin.c b/avrdude/ppiwin.c new file mode 100644 index 00000000..bf9a3c39 --- /dev/null +++ b/avrdude/ppiwin.c @@ -0,0 +1,418 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003, 2004, 2006 + * Eric B. Weddington + * Copyright 2008, Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* +This is the parallel port interface for Windows built using Cygwin. + +In the ppi_* functions that access the parallel port registers, +fd = parallel port address +reg = register as defined in an enum in ppi.h. This must be converted + to a proper offset of the base address. +*/ + + +#include "ac_cfg.h" +#include "avrdude.h" + +#if defined (WIN32NATIVE) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "ppi.h" + +#define DEVICE_LPT1 "lpt1" +#define DEVICE_LPT2 "lpt2" +#define DEVICE_LPT3 "lpt3" + +#define DEVICE_MAX 3 + +typedef struct +{ + const char *name; + int base_address; +} winpp; + +static const winpp winports[DEVICE_MAX] = +{ + {DEVICE_LPT1, 0x378}, + {DEVICE_LPT2, 0x278}, + {DEVICE_LPT3, 0x3BC}, +}; + + + + + +/* FUNCTION PROTOTYPES */ +static int winnt_pp_open(void); +static unsigned short port_get(union filedescriptor *fdp, int reg); +static unsigned char reg2offset(int reg); +static unsigned char inb(unsigned short port); +static void outb(unsigned char value, unsigned short port); + + + +/* FUNCTION DEFINITIONS */ + +void ppi_open(char *port, union filedescriptor *fdp) +{ + unsigned char i; + int fd; + + fd = winnt_pp_open(); + + if(fd < 0) + { + fprintf(stderr, "%s: can't open device \"giveio\"\n\n", progname); + fdp->ifd = -1; + return; + } + + /* Search the windows port names for a match */ + fd = -1; + for(i = 0; i < DEVICE_MAX; i++) + { + if(strcmp(winports[i].name, port) == 0) + { + /* Set the file descriptor with the Windows parallel port base address. */ + fd = winports[i].base_address; + break; + } + } + if(fd == -1) + { + /* + * Supplied port name did not match any of the pre-defined + * names. Try interpreting it as a numeric + * (hexadecimal/decimal/octal) address. + */ + char *cp; + + fd = strtol(port, &cp, 0); + if(*port == '\0' || *cp != '\0') + { + fprintf(stderr, + "%s: port name \"%s\" is neither lpt1/2/3 nor valid number\n", + progname, port); + fd = -1; + } + } + if(fd < 0) + { + fprintf(stderr, "%s: can't open device \"%s\"\n\n", progname, port); + fdp->ifd = -1; + return; + } + + fdp->ifd = fd; +} + + +#define DRIVERNAME "\\\\.\\giveio" +static int winnt_pp_open(void) +{ + // Only try to use giveio under Windows NT/2000/XP. + OSVERSIONINFO ver_info; + + memset(&ver_info, 0, sizeof(ver_info)); + + ver_info.dwOSVersionInfoSize = sizeof(ver_info); + + if(!GetVersionEx(&ver_info)) + { + return(-1); + } + else if(ver_info.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + HANDLE h = CreateFile(DRIVERNAME, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(h == INVALID_HANDLE_VALUE) + { + return(-1); + } + + /* Close immediately. The process now has the rights it needs. */ + if(h != NULL) + { + CloseHandle(h); + } + } + return(0); +} + + + + +void ppi_close(union filedescriptor *fdp) +{ + return; +} + + + +/* + * set the indicated bit of the specified register. + */ +int ppi_set(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + unsigned short port; + + port = port_get(fdp, reg); + v = inb(port); + v |= bit; + outb(v, port); + return 0; +} + + +/* + * clear the indicated bit of the specified register. + */ +int ppi_clr(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + unsigned short port; + + port = port_get(fdp, reg); + v = inb(port); + v &= ~bit; + outb(v, port); + + return 0; +} + + +/* + * get the indicated bit of the specified register. + */ +int ppi_get(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + + v = inb(port_get(fdp, reg)); + v &= bit; + + return(v); +} + + + + +/* + * toggle the indicated bit of the specified register. + */ +int ppi_toggle(union filedescriptor *fdp, int reg, int bit) +{ + unsigned char v; + unsigned short port; + + port = port_get(fdp, reg); + + v = inb(port); + v ^= bit; + outb(v, port); + + return 0; +} + + +/* + * get all bits of the specified register. + */ +int ppi_getall(union filedescriptor *fdp, int reg) +{ + unsigned char v; + + v = inb(port_get(fdp, reg)); + + return((int)v); +} + + + + +/* + * set all bits of the specified register to val. + */ +int ppi_setall(union filedescriptor *fdp, int reg, int val) +{ + outb((unsigned char)val, port_get(fdp, reg)); + return 0; +} + + + + +/* Calculate port address to access. */ +static unsigned short port_get(union filedescriptor *fdp, int reg) +{ + return((unsigned short)(fdp->ifd + reg2offset(reg))); +} + + +/* Convert register enum to offset of base address. */ +static unsigned char reg2offset(int reg) +{ + unsigned char offset = 0; + + switch(reg) + { + case PPIDATA: + { + offset = 0; + break; + } + case PPISTATUS: + { + offset = 1; + break; + } + case PPICTRL: + { + offset = 2; + break; + } + } + + return(offset); +} + + +/* Read in value from port. */ +static unsigned char inb(unsigned short port) +{ + unsigned char t; + + asm volatile ("in %1, %0" + : "=a" (t) + : "d" (port)); + + return t; +} + + +/* Write value to port. */ +static void outb(unsigned char value, unsigned short port) +{ + asm volatile ("out %1, %0" + : + : "d" (port), "a" (value) ); + + return; +} + +#if !defined(HAVE_GETTIMEOFDAY) +struct timezone; +int gettimeofday(struct timeval *tv, struct timezone *unused){ +// i've found only ms resolution, avrdude expects us + + SYSTEMTIME st; + GetSystemTime(&st); + + tv->tv_sec=(long)(st.wSecond+st.wMinute*60+st.wHour*3600); + tv->tv_usec=(long)(st.wMilliseconds*1000); + + return 0; +} +#endif /* HAVE_GETTIMEOFDAY */ + +// #define W32USLEEPDBG + +#ifdef W32USLEEPDBG + +# define DEBUG_QueryPerformanceCounter(arg) QueryPerformanceCounter(arg) +# define DEBUG_DisplayTimingInfo(start, stop, freq, us, has_highperf) \ + do { \ + unsigned long dt; \ + dt = (unsigned long)((stop.QuadPart - start.QuadPart) * 1000 * 1000 \ + / freq.QuadPart); \ + fprintf(stderr, \ + "hpt:%i usleep usec:%lu sleep msec:%lu timed usec:%lu\n", \ + has_highperf, us, ((us + 999) / 1000), dt); \ + } while (0) + +#else + +# define DEBUG_QueryPerformanceCounter(arg) +# define DEBUG_DisplayTimingInfo(start, stop, freq, us, has_highperf) + +#endif + +#if !defined(HAVE_USLEEP) +int usleep(unsigned int us) +{ + int has_highperf; + LARGE_INTEGER freq,start,stop,loopend; + + // workaround: although usleep is very precise if using + // high-performance-timers there are sometimes problems with + // verify - increasing the delay helps sometimes but not + // realiably. There must be some other problem. Maybe just + // with my test-hardware maybe in the code-base. + //// us=(unsigned long) (us*1.5); + + has_highperf=QueryPerformanceFrequency(&freq); + + //has_highperf=0; // debug + + if (has_highperf) { + QueryPerformanceCounter(&start); + loopend.QuadPart=start.QuadPart+freq.QuadPart*us/(1000*1000); + do { + QueryPerformanceCounter(&stop); + } while (stop.QuadPart<=loopend.QuadPart); + } + else { + DEBUG_QueryPerformanceCounter(&start); + + Sleep(1); + Sleep( (DWORD)((us+999)/1000) ); + + DEBUG_QueryPerformanceCounter(&stop); + } + + DEBUG_DisplayTimingInfo(start, stop, freq, us, has_highperf); + + return 0; +} +#endif /* !HAVE_USLEEP */ + +#endif + + diff --git a/avrdude/safemode.c b/avrdude/safemode.c new file mode 100644 index 00000000..ad1b9cc3 --- /dev/null +++ b/avrdude/safemode.c @@ -0,0 +1,363 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * avrdude is Copyright (C) 2000-2004 Brian S. Dean + * + * This file: Copyright (C) 2005-2007 Colin O'Flynn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include + +#include "ac_cfg.h" +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "safemode.h" + +/* This value from ac_cfg.h */ +/* + * Writes the specified fuse in fusename (can be "lfuse", "hfuse", or + * "efuse") and verifies it. Will try up to tries amount of times + * before giving up + */ +int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, + AVRPART * p, int tries, int verbose) +{ + AVRMEM * m; + unsigned char fuseread; + int returnvalue = -1; + + m = avr_locate_mem(p, fusename); + if (m == NULL) { + return -1; + } + + /* Keep trying to write then read back the fuse values */ + while (tries > 0) { + if (avr_write_byte(pgm, p, m, 0, fuse) != 0) + { + continue; + } + if (pgm->read_byte(pgm, p, m, 0, &fuseread) != 0) + { + continue; + } + + /* Report information to user if needed */ + if (verbose > 0) { + fprintf(stderr, + "%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n", + progname, fusename, fuse, fuseread, tries-1); + } + + /* If fuse wrote OK, no need to keep going */ + if (fuse == fuseread) { + tries = 0; + returnvalue = 0; + } + tries--; + } + + return returnvalue; +} + +/* + * Reads the fuses three times, checking that all readings are the + * same. This will ensure that the before values aren't in error! + */ +int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, + unsigned char * efuse, unsigned char * fuse, + PROGRAMMER * pgm, AVRPART * p, int verbose) +{ + + unsigned char value; + unsigned char fusegood = 0; + unsigned char allowfuseread = 1; + unsigned char safemode_lfuse; + unsigned char safemode_hfuse; + unsigned char safemode_efuse; + unsigned char safemode_fuse; + AVRMEM * m; + + safemode_lfuse = *lfuse; + safemode_hfuse = *hfuse; + safemode_efuse = *efuse; + safemode_fuse = *fuse; + + + /* Read fuse three times */ + fusegood = 2; /* If AVR device doesn't support this fuse, don't want + to generate a verify error */ + m = avr_locate_mem(p, "fuse"); + if (m != NULL) { + fusegood = 0; /* By default fuse is a failure */ + if(pgm->read_byte(pgm, p, m, 0, &safemode_fuse) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 1, fuse value: %x\n",progname, safemode_fuse); + } + if(pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 2, fuse value: %x\n",progname, value); + } + if (value == safemode_fuse) { + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 3, fuse value: %x\n",progname, value); + } + if (value == safemode_fuse) + { + fusegood = 1; /* Fuse read OK three times */ + } + } + } + + //Programmer does not allow fuse reading.... no point trying anymore + if (allowfuseread == 0) + { + return -5; + } + + if (fusegood == 0) { + fprintf(stderr, + "%s: safemode: Verify error - unable to read fuse properly. " + "Programmer may not be reliable.\n", progname); + return -1; + } + else if ((fusegood == 1) && (verbose > 0)) { + fprintf(stderr, "%s: safemode: fuse reads as %X\n", progname, safemode_fuse); + } + + + /* Read lfuse three times */ + fusegood = 2; /* If AVR device doesn't support this fuse, don't want + to generate a verify error */ + m = avr_locate_mem(p, "lfuse"); + if (m != NULL) { + fusegood = 0; /* By default fuse is a failure */ + if (pgm->read_byte(pgm, p, m, 0, &safemode_lfuse) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 1, lfuse value: %x\n",progname, safemode_lfuse); + } + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 2, lfuse value: %x\n",progname, value); + } + if (value == safemode_lfuse) { + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 3, lfuse value: %x\n",progname, value); + } + if (value == safemode_lfuse){ + fusegood = 1; /* Fuse read OK three times */ + } + } + } + + //Programmer does not allow fuse reading.... no point trying anymore + if (allowfuseread == 0) + { + return -5; + } + + + if (fusegood == 0) { + fprintf(stderr, + "%s: safemode: Verify error - unable to read lfuse properly. " + "Programmer may not be reliable.\n", progname); + return -1; + } + else if ((fusegood == 1) && (verbose > 0)) { + fprintf(stderr, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse); + } + + /* Read hfuse three times */ + fusegood = 2; /* If AVR device doesn't support this fuse, don't want + to generate a verify error */ + m = avr_locate_mem(p, "hfuse"); + if (m != NULL) { + fusegood = 0; /* By default fuse is a failure */ + if (pgm->read_byte(pgm, p, m, 0, &safemode_hfuse) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 1, hfuse value: %x\n",progname, safemode_hfuse); + } + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 2, hfuse value: %x\n",progname, value); + } + if (value == safemode_hfuse) { + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 3, hfuse value: %x\n",progname, value); + } + if (value == safemode_hfuse){ + fusegood = 1; /* Fuse read OK three times */ + } + } + } + + //Programmer does not allow fuse reading.... no point trying anymore + if (allowfuseread == 0) + { + return -5; + } + + if (fusegood == 0) { + fprintf(stderr, + "%s: safemode: Verify error - unable to read hfuse properly. " + "Programmer may not be reliable.\n", progname); + return -2; + } + else if ((fusegood == 1) && (verbose > 0)){ + fprintf(stderr, "%s: safemode: hfuse reads as %X\n", progname, safemode_hfuse); + } + + /* Read efuse three times */ + fusegood = 2; /* If AVR device doesn't support this fuse, don't want + to generate a verify error */ + m = avr_locate_mem(p, "efuse"); + if (m != NULL) { + fusegood = 0; /* By default fuse is a failure */ + if (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 1, efuse value: %x\n",progname, safemode_efuse); + } + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 2, efuse value: %x\n",progname, value); + } + if (value == safemode_efuse) { + if (pgm->read_byte(pgm, p, m, 0, &value) != 0) + { + allowfuseread = 0; + } + if (verbose > 2) + { + fprintf(stderr, "%s: safemode read 3, efuse value: %x\n",progname, value); + } + if (value == safemode_efuse){ + fusegood = 1; /* Fuse read OK three times */ + } + } + } + + //Programmer does not allow fuse reading.... no point trying anymore + if (allowfuseread == 0) + { + return -5; + } + + if (fusegood == 0) { + fprintf(stderr, + "%s: safemode: Verify error - unable to read efuse properly. " + "Programmer may not be reliable.\n", progname); + return -3; + } + else if ((fusegood == 1) && (verbose > 0)) { + fprintf(stderr, "%s: safemode: efuse reads as %X\n", progname, safemode_efuse); + } + + *lfuse = safemode_lfuse; + *hfuse = safemode_hfuse; + *efuse = safemode_efuse; + *fuse = safemode_fuse; + + return 0; +} + + +/* + * This routine will store the current values pointed to by lfuse, + * hfuse, and efuse into an internal buffer in this routine when save + * is set to 1. When save is 0 (or not 1 really) it will copy the + * values from the internal buffer into the locations pointed to be + * lfuse, hfuse, and efuse. This allows you to change the fuse bits if + * needed from another routine (ie: have it so if user requests fuse + * bits are changed, the requested value is now verified + */ +int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, + unsigned char * efuse, unsigned char * fuse) +{ + static unsigned char safemode_lfuse = 0xff; + static unsigned char safemode_hfuse = 0xff; + static unsigned char safemode_efuse = 0xff; + static unsigned char safemode_fuse = 0xff; + + switch (save) { + + /* Save the fuses as safemode setting */ + case 1: + safemode_lfuse = *lfuse; + safemode_hfuse = *hfuse; + safemode_efuse = *efuse; + safemode_fuse = *fuse; + + break; + /* Read back the fuses */ + default: + *lfuse = safemode_lfuse; + *hfuse = safemode_hfuse; + *efuse = safemode_efuse; + *fuse = safemode_fuse; + break; + } + + return 0; +} diff --git a/avrdude/safemode.h b/avrdude/safemode.h new file mode 100644 index 00000000..4c8ba4fa --- /dev/null +++ b/avrdude/safemode.h @@ -0,0 +1,47 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * avrdude is Copyright (C) 2000-2004 Brian S. Dean + * + * This file: Copyright (C) 2005 Colin O'Flynn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef safemode_h +#define safemode_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or "efuse") and verifies it. Will try up to tries +amount of times before giving up */ +int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries, int verbose); + +/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */ +int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p, int verbose); + +/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine +when save is set to 1. When save is 0 (or not 1 really) it will copy the values from the internal buffer into the locations +pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so +if user requests fuse bits are changed, the requested value is now verified */ +int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse); + +#ifdef __cplusplus +} +#endif + +#endif /* safemode_h */ diff --git a/avrdude/ser_avrdoper.c b/avrdude/ser_avrdoper.c new file mode 100644 index 00000000..5a8e59fa --- /dev/null +++ b/avrdude/ser_avrdoper.c @@ -0,0 +1,659 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * Copyright (C) 2006 Joerg Wunsch + * Copyright (C) 2006 Christian Starkjohann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Serial Interface emulation for USB programmer "AVR-Doper" in HID mode. + */ + +#include "ac_cfg.h" + +#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) + +#include +#include +#include + +#include "avrdude.h" +#include "serial.h" + +/* ------------------------------------------------------------------------ */ + +/* Numeric constants for 'reportType' parameters */ +#define USB_HID_REPORT_TYPE_INPUT 1 +#define USB_HID_REPORT_TYPE_OUTPUT 2 +#define USB_HID_REPORT_TYPE_FEATURE 3 + +/* These are the error codes which can be returned by functions of this + * module. + */ +#define USB_ERROR_NONE 0 +#define USB_ERROR_ACCESS 1 +#define USB_ERROR_NOTFOUND 2 +#define USB_ERROR_BUSY 16 +#define USB_ERROR_IO 5 + +#define USB_VENDOR_ID 0x16c0 +#define USB_PRODUCT_ID 0x05df + +static int reportDataSizes[4] = {13, 29, 61, 125}; + +static unsigned char avrdoperRxBuffer[280]; /* buffer for receive data */ +static int avrdoperRxLength = 0; /* amount of valid bytes in rx buffer */ +static int avrdoperRxPosition = 0; /* amount of bytes already consumed in rx buffer */ + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +#if defined(WIN32NATIVE) && defined(HAVE_LIBHID) + +#include +#include + +#if defined(HAVE_DDK_HIDSDI_H) +# include +#else +# include "my_ddk_hidsdi.h" +#endif +#include + +#ifdef USB_DEBUG +#define DEBUG_PRINT(arg) printf arg +#else +#define DEBUG_PRINT(arg) +#endif + +/* ------------------------------------------------------------------------ */ + +static void convertUniToAscii(char *buffer) +{ + unsigned short *uni = (void *)buffer; + char *ascii = buffer; + + while(*uni != 0){ + if(*uni >= 256){ + *ascii++ = '?'; + uni++; + }else{ + *ascii++ = *uni++; + } + } + *ascii++ = 0; +} + +static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName, + int product, char *productName, int usesReportIDs) +{ + GUID hidGuid; /* GUID for HID driver */ + HDEVINFO deviceInfoList; + SP_DEVICE_INTERFACE_DATA deviceInfo; + SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL; + DWORD size; + int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */ + int errorCode = USB_ERROR_NOTFOUND; + HANDLE handle = INVALID_HANDLE_VALUE; + HIDD_ATTRIBUTES deviceAttributes; + + HidD_GetHidGuid(&hidGuid); + deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, + DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); + deviceInfo.cbSize = sizeof(deviceInfo); + for(i=0;;i++){ + if(handle != INVALID_HANDLE_VALUE){ + CloseHandle(handle); + handle = INVALID_HANDLE_VALUE; + } + if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo)) + break; /* no more entries */ + /* first do a dummy call just to determine the actual size required */ + SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL); + if(deviceDetails != NULL) + free(deviceDetails); + deviceDetails = malloc(size); + deviceDetails->cbSize = sizeof(*deviceDetails); + /* this call is for real: */ + SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, + size, &size, NULL); + DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath)); + /* attempt opening for R/W -- we don't care about devices which can't be accessed */ + handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + openFlag, NULL); + if(handle == INVALID_HANDLE_VALUE){ + DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError())); + /* errorCode = USB_ERROR_ACCESS; opening will always fail for mouse -- ignore */ + continue; + } + deviceAttributes.Size = sizeof(deviceAttributes); + HidD_GetAttributes(handle, &deviceAttributes); + DEBUG_PRINT(("device attributes: vid=%d pid=%d\n", + deviceAttributes.VendorID, deviceAttributes.ProductID)); + if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product) + continue; /* ignore this device */ + errorCode = USB_ERROR_NOTFOUND; + if(vendorName != NULL && productName != NULL){ + char buffer[512]; + if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){ + DEBUG_PRINT(("error obtaining vendor name\n")); + errorCode = USB_ERROR_IO; + continue; + } + convertUniToAscii(buffer); + DEBUG_PRINT(("vendorName = \"%s\"\n", buffer)); + if(strcmp(vendorName, buffer) != 0) + continue; + if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){ + DEBUG_PRINT(("error obtaining product name\n")); + errorCode = USB_ERROR_IO; + continue; + } + convertUniToAscii(buffer); + DEBUG_PRINT(("productName = \"%s\"\n", buffer)); + if(strcmp(productName, buffer) != 0) + continue; + } + break; /* we have found the device we are looking for! */ + } + SetupDiDestroyDeviceInfoList(deviceInfoList); + if(deviceDetails != NULL) + free(deviceDetails); + if(handle != INVALID_HANDLE_VALUE){ + fdp->pfd = (void *)handle; + errorCode = 0; + } + return errorCode; +} + +/* ------------------------------------------------------------------------ */ + +static void usbCloseDevice(union filedescriptor *fdp) +{ + CloseHandle((HANDLE)fdp->pfd); +} + +/* ------------------------------------------------------------------------ */ + +static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len) +{ + HANDLE handle = (HANDLE)fdp->pfd; + BOOLEAN rval = 0; + DWORD bytesWritten; + + switch(reportType){ + case USB_HID_REPORT_TYPE_INPUT: + break; + case USB_HID_REPORT_TYPE_OUTPUT: + rval = WriteFile(handle, buffer, len, &bytesWritten, NULL); + break; + case USB_HID_REPORT_TYPE_FEATURE: + rval = HidD_SetFeature(handle, buffer, len); + break; + } + return rval == 0 ? USB_ERROR_IO : 0; +} + +/* ------------------------------------------------------------------------ */ + +static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber, + char *buffer, int *len) +{ + HANDLE handle = (HANDLE)fdp->pfd; + BOOLEAN rval = 0; + DWORD bytesRead; + + switch(reportType){ + case USB_HID_REPORT_TYPE_INPUT: + buffer[0] = reportNumber; + rval = ReadFile(handle, buffer, *len, &bytesRead, NULL); + if(rval) + *len = bytesRead; + break; + case USB_HID_REPORT_TYPE_OUTPUT: + break; + case USB_HID_REPORT_TYPE_FEATURE: + buffer[0] = reportNumber; + rval = HidD_GetFeature(handle, buffer, *len); + break; + } + return rval == 0 ? USB_ERROR_IO : 0; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +#else /* !(WIN32NATIVE && HAVE_LIBHID) */ + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +#include + +/* ------------------------------------------------------------------------- */ + +#define USBRQ_HID_GET_REPORT 0x01 +#define USBRQ_HID_SET_REPORT 0x09 + +static int usesReportIDs; + +/* ------------------------------------------------------------------------- */ + +static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen) +{ + char buffer[256]; + int rval, i; + + if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) + index, langid, buffer, + sizeof(buffer), 1000)) < 0) + return rval; + if(buffer[1] != USB_DT_STRING) + return 0; + if((unsigned char)buffer[0] < rval) + rval = (unsigned char)buffer[0]; + rval /= 2; + /* lossy conversion to ISO Latin1 */ + for(i=1;i buflen) /* destination buffer overflow */ + break; + buf[i-1] = buffer[2 * i]; + if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */ + buf[i-1] = '?'; + } + buf[i-1] = 0; + return i-1; +} + +static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName, + int product, char *productName, int doReportIDs) +{ + struct usb_bus *bus; + struct usb_device *dev; + usb_dev_handle *handle = NULL; + int errorCode = USB_ERROR_NOTFOUND; + static int didUsbInit = 0; + + if(!didUsbInit){ + usb_init(); + didUsbInit = 1; + } + usb_find_busses(); + usb_find_devices(); + for(bus=usb_get_busses(); bus; bus=bus->next){ + for(dev=bus->devices; dev; dev=dev->next){ + if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){ + char string[256]; + int len; + handle = usb_open(dev); /* we need to open the device in order to query strings */ + if(!handle){ + errorCode = USB_ERROR_ACCESS; + fprintf(stderr, "Warning: cannot open USB device: %s\n", + usb_strerror()); + continue; + } + if(vendorName == NULL && productName == NULL){ /* name does not matter */ + break; + } + /* now check whether the names match: */ + len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, + 0x0409, string, sizeof(string)); + if(len < 0){ + errorCode = USB_ERROR_IO; + fprintf(stderr, + "Warning: cannot query manufacturer for device: %s\n", + usb_strerror()); + }else{ + errorCode = USB_ERROR_NOTFOUND; + /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */ + if(strcmp(string, vendorName) == 0){ + len = usbGetStringAscii(handle, dev->descriptor.iProduct, + 0x0409, string, sizeof(string)); + if(len < 0){ + errorCode = USB_ERROR_IO; + fprintf(stderr, + "Warning: cannot query product for device: %s\n", + usb_strerror()); + }else{ + errorCode = USB_ERROR_NOTFOUND; + /* fprintf(stderr, "seen product ->%s<-\n", string); */ + if(strcmp(string, productName) == 0) + break; + } + } + } + usb_close(handle); + handle = NULL; + } + } + if(handle) + break; + } + if(handle != NULL){ + int rval, retries = 3; + if(usb_set_configuration(handle, 1)){ + fprintf(stderr, "Warning: could not set configuration: %s\n", + usb_strerror()); + } + /* now try to claim the interface and detach the kernel HID driver on + * linux and other operating systems which support the call. + */ + while((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0){ +#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP + if(usb_detach_kernel_driver_np(handle, 0) < 0){ + fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n", + usb_strerror()); + } +#endif + } + if(rval != 0) + fprintf(stderr, "Warning: could not claim interface\n"); +/* Continue anyway, even if we could not claim the interface. Control transfers + * should still work. + */ + errorCode = 0; + fdp->pfd = (void *)handle; + usesReportIDs = doReportIDs; + } + return errorCode; +} + +/* ------------------------------------------------------------------------- */ + +static void usbCloseDevice(union filedescriptor *fdp) +{ + usb_close((usb_dev_handle *)fdp->pfd); +} + +/* ------------------------------------------------------------------------- */ + +static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len) +{ + int bytesSent; + + if(!usesReportIDs){ + buffer++; /* skip dummy report ID */ + len--; + } + bytesSent = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS | + USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, + reportType << 8 | buffer[0], 0, buffer, len, 5000); + if(bytesSent != len){ + if(bytesSent < 0) + fprintf(stderr, "Error sending message: %s\n", usb_strerror()); + return USB_ERROR_IO; + } + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber, + char *buffer, int *len) +{ + int bytesReceived, maxLen = *len; + + if(!usesReportIDs){ + buffer++; /* make room for dummy report ID */ + maxLen--; + } + bytesReceived = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS | + USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, + reportType << 8 | reportNumber, 0, buffer, maxLen, 5000); + if(bytesReceived < 0){ + fprintf(stderr, "Error sending message: %s\n", usb_strerror()); + return USB_ERROR_IO; + } + *len = bytesReceived; + if(!usesReportIDs){ + buffer[-1] = reportNumber; /* add dummy report ID */ + len++; + } + return 0; +} + +#endif /* WIN32NATIVE */ + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +/* ------------------------------------------------------------------------- */ + +static void dumpBlock(char *prefix, unsigned char *buf, int len) +{ + int i; + + if(len <= 8){ /* more compact format for short blocks */ + fprintf(stderr, "%s: %d bytes: ", prefix, len); + for(i = 0; i < len; i++){ + fprintf(stderr, "%02x ", buf[i]); + } + fprintf(stderr, " \""); + for(i = 0; i < len; i++){ + if(buf[i] >= 0x20 && buf[i] < 0x7f){ + fputc(buf[i], stderr); + }else{ + fputc('.', stderr); + } + } + fprintf(stderr, "\"\n"); + }else{ + fprintf(stderr, "%s: %d bytes:\n", prefix, len); + while(len > 0){ + for(i = 0; i < 16; i++){ + if(i < len){ + fprintf(stderr, "%02x ", buf[i]); + }else{ + fprintf(stderr, " "); + } + if(i == 7) + fputc(' ', stderr); + } + fprintf(stderr, " \""); + for(i = 0; i < 16; i++){ + if(i < len){ + if(buf[i] >= 0x20 && buf[i] < 0x7f){ + fputc(buf[i], stderr); + }else{ + fputc('.', stderr); + } + } + } + fprintf(stderr, "\"\n"); + buf += 16; + len -= 16; + } + } +} + +static char *usbErrorText(int usbErrno) +{ + static char buffer[32]; + + switch(usbErrno){ + case USB_ERROR_NONE: return "Success."; + case USB_ERROR_ACCESS: return "Access denied."; + case USB_ERROR_NOTFOUND:return "Device not found."; + case USB_ERROR_BUSY: return "Device is busy."; + case USB_ERROR_IO: return "I/O Error."; + default: + sprintf(buffer, "Unknown error %d.", usbErrno); + return buffer; + } +} + +/* ------------------------------------------------------------------------- */ + +static int avrdoper_open(char *port, long baud, union filedescriptor *fdp) +{ + int rval; + char *vname = "obdev.at"; + char *devname = "AVR-Doper"; + + rval = usbOpenDevice(fdp, USB_VENDOR_ID, vname, USB_PRODUCT_ID, devname, 1); + if(rval != 0){ + fprintf(stderr, "%s: avrdoper_open(): %s\n", progname, usbErrorText(rval)); + exit(1); + //return -1; + } + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void avrdoper_close(union filedescriptor *fdp) +{ + usbCloseDevice(fdp); +} + +/* ------------------------------------------------------------------------- */ + +static int chooseDataSize(int len) +{ + int i; + + for(i = 0; i < sizeof(reportDataSizes)/sizeof(reportDataSizes[0]); i++){ + if(reportDataSizes[i] >= len) + return i; + } + return i - 1; +} + +static int avrdoper_send(union filedescriptor *fdp, unsigned char *buf, size_t buflen) +{ + if(verbose > 3) + dumpBlock("Send", buf, buflen); + while(buflen > 0){ + unsigned char buffer[256]; + int rval, lenIndex = chooseDataSize(buflen); + int thisLen = buflen > reportDataSizes[lenIndex] ? + reportDataSizes[lenIndex] : buflen; + buffer[0] = lenIndex + 1; /* report ID */ + buffer[1] = thisLen; + memcpy(buffer + 2, buf, thisLen); + if(verbose > 3) + fprintf(stderr, "Sending %d bytes data chunk\n", thisLen); + rval = usbSetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, (char *)buffer, + reportDataSizes[lenIndex] + 2); + if(rval != 0){ + fprintf(stderr, "%s: avrdoper_send(): %s\n", progname, usbErrorText(rval)); + exit(1); + } + buflen -= thisLen; + buf += thisLen; + } + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void avrdoperFillBuffer(union filedescriptor *fdp) +{ + int bytesPending = reportDataSizes[1]; /* guess how much data is buffered in device */ + + avrdoperRxPosition = avrdoperRxLength = 0; + while(bytesPending > 0){ + int len, usbErr, lenIndex = chooseDataSize(bytesPending); + unsigned char buffer[128]; + len = sizeof(avrdoperRxBuffer) - avrdoperRxLength; /* bytes remaining */ + if(reportDataSizes[lenIndex] + 2 > len) /* requested data would not fit into buffer */ + break; + len = reportDataSizes[lenIndex] + 2; + usbErr = usbGetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, lenIndex + 1, + (char *)buffer, &len); + if(usbErr != 0){ + fprintf(stderr, "%s: avrdoperFillBuffer(): %s\n", progname, usbErrorText(usbErr)); + exit(1); + } + if(verbose > 3) + fprintf(stderr, "Received %d bytes data chunk of total %d\n", len - 2, buffer[1]); + len -= 2; /* compensate for report ID and length byte */ + bytesPending = buffer[1] - len; /* amount still buffered */ + if(len > buffer[1]) /* cut away padding */ + len = buffer[1]; + if(avrdoperRxLength + len > sizeof(avrdoperRxBuffer)){ + fprintf(stderr, + "%s: avrdoperFillBuffer(): internal error: buffer overflow\n", + progname); + exit(1); + } + memcpy(avrdoperRxBuffer + avrdoperRxLength, buffer + 2, len); + avrdoperRxLength += len; + } +} + +static int avrdoper_recv(union filedescriptor *fdp, unsigned char *buf, size_t buflen) +{ + unsigned char *p = buf; + int remaining = buflen; + + while(remaining > 0){ + int len, available = avrdoperRxLength - avrdoperRxPosition; + if(available <= 0){ /* buffer is empty */ + avrdoperFillBuffer(fdp); + continue; + } + len = remaining < available ? remaining : available; + memcpy(p, avrdoperRxBuffer + avrdoperRxPosition, len); + p += len; + remaining -= len; + avrdoperRxPosition += len; + } + if(verbose > 3) + dumpBlock("Receive", buf, buflen); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static int avrdoper_drain(union filedescriptor *fdp, int display) +{ + do{ + avrdoperFillBuffer(fdp); + }while(avrdoperRxLength > 0); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static int avrdoper_set_dtr_rts(union filedescriptor *fdp, int is_on) +{ + fprintf(stderr, "%s: AVR-Doper doesn't support DTR/RTS setting\n", progname); + return -1; +} + +/* ------------------------------------------------------------------------- */ + +struct serial_device avrdoper_serdev = +{ + .open = avrdoper_open, + .close = avrdoper_close, + .send = avrdoper_send, + .recv = avrdoper_recv, + .drain = avrdoper_drain, + .set_dtr_rts = avrdoper_set_dtr_rts, + .flags = SERDEV_FL_NONE, +}; + +#endif /* defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) */ diff --git a/avrdude/ser_posix.c b/avrdude/ser_posix.c new file mode 100644 index 00000000..210bff20 --- /dev/null +++ b/avrdude/ser_posix.c @@ -0,0 +1,503 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Posix serial interface for avrdude. + */ + +#if !defined(WIN32NATIVE) + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "avrdude.h" +#include "serial.h" + +long serial_recv_timeout = 5000; /* ms */ + +struct baud_mapping { + long baud; + speed_t speed; +}; + +/* There are a lot more baud rates we could handle, but what's the point? */ + +static struct baud_mapping baud_lookup_table [] = { + { 1200, B1200 }, + { 2400, B2400 }, + { 4800, B4800 }, + { 9600, B9600 }, + { 19200, B19200 }, + { 38400, B38400 }, + { 57600, B57600 }, + { 115200, B115200 }, + { 230400, B230400 }, + { 0, 0 } /* Terminator. */ +}; + +static struct termios original_termios; +static int saved_original_termios; + +static speed_t serial_baud_lookup(long baud) +{ + struct baud_mapping *map = baud_lookup_table; + + while (map->baud) { + if (map->baud == baud) + return map->speed; + map++; + } + + /* + * If a non-standard BAUD rate is used, issue + * a warning (if we are verbose) and return the raw rate + */ + if (verbose > 0) + fprintf(stderr, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld", + progname, baud); + + return baud; +} + +static int ser_setspeed(union filedescriptor *fd, long baud) +{ + int rc; + struct termios termios; + speed_t speed = serial_baud_lookup (baud); + + if (!isatty(fd->ifd)) + return -ENOTTY; + + /* + * initialize terminal modes + */ + rc = tcgetattr(fd->ifd, &termios); + if (rc < 0) { + fprintf(stderr, "%s: ser_setspeed(): tcgetattr() failed", + progname); + return -errno; + } + + /* + * copy termios for ser_close if we haven't already + */ + if (! saved_original_termios++) { + original_termios = termios; + } + + termios.c_iflag = IGNBRK; + termios.c_oflag = 0; + termios.c_lflag = 0; + termios.c_cflag = (CS8 | CREAD | CLOCAL); + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; + + cfsetospeed(&termios, speed); + cfsetispeed(&termios, speed); + + rc = tcsetattr(fd->ifd, TCSANOW, &termios); + if (rc < 0) { + fprintf(stderr, "%s: ser_setspeed(): tcsetattr() failed\n", + progname); + return -errno; + } + + /* + * Everything is now set up for a local line without modem control + * or flow control, so clear O_NONBLOCK again. + */ + rc = fcntl(fd->ifd, F_GETFL, 0); + if (rc != -1) + fcntl(fd->ifd, F_SETFL, rc & ~O_NONBLOCK); + + return 0; +} + +/* + * Given a port description of the form :, open a TCP + * connection to the specified destination, which is assumed to be a + * terminal/console server with serial parameters configured + * appropriately (e. g. 115200-8-N-1 for a STK500.) + */ +static int +net_open(const char *port, union filedescriptor *fdp) +{ + char *hstr, *pstr, *end; + unsigned int pnum; + int fd; + struct sockaddr_in sockaddr; + struct hostent *hp; + + if ((hstr = strdup(port)) == NULL) { + fprintf(stderr, "%s: net_open(): Out of memory!\n", + progname); + return -1; + } + + if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) { + fprintf(stderr, "%s: net_open(): Mangled host:port string \"%s\"\n", + progname, hstr); + free(hstr); + return -1; + } + + /* + * Terminate the host section of the description. + */ + *pstr++ = '\0'; + + pnum = strtoul(pstr, &end, 10); + + if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) { + fprintf(stderr, "%s: net_open(): Bad port number \"%s\"\n", + progname, pstr); + free(hstr); + return -1; + } + + if ((hp = gethostbyname(hstr)) == NULL) { + fprintf(stderr, "%s: net_open(): unknown host \"%s\"\n", + progname, hstr); + free(hstr); + return -1; + } + + free(hstr); + + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "%s: net_open(): Cannot open socket: %s\n", + progname, strerror(errno)); + return -1; + } + + memset(&sockaddr, 0, sizeof(struct sockaddr_in)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(pnum); + memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr)); + + if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { + fprintf(stderr, "%s: net_open(): Connect failed: %s\n", + progname, strerror(errno)); + return -1; + } + + fdp->ifd = fd; + return 0; +} + + +static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on) +{ + unsigned int ctl; + int r; + + r = ioctl(fdp->ifd, TIOCMGET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMGET\")"); + return -1; + } + + if (is_on) { + /* Set DTR and RTS */ + ctl |= (TIOCM_DTR | TIOCM_RTS); + } + else { + /* Clear DTR and RTS */ + ctl &= ~(TIOCM_DTR | TIOCM_RTS); + } + + r = ioctl(fdp->ifd, TIOCMSET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMSET\")"); + return -1; + } + + return 0; +} + +static int ser_open(char * port, long baud, union filedescriptor *fdp) +{ + int rc; + int fd; + + /* + * If the port is of the form "net::", then + * handle it as a TCP connection to a terminal server. + */ + if (strncmp(port, "net:", strlen("net:")) == 0) { + return net_open(port + strlen("net:"), fdp); + } + + /* + * open the serial port + */ + fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fd < 0) { + fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n", + progname, port, strerror(errno)); + return -1; + } + + fdp->ifd = fd; + + /* + * set serial line attributes + */ + rc = ser_setspeed(fdp, baud); + if (rc) { + fprintf(stderr, + "%s: ser_open(): can't set attributes for device \"%s\": %s\n", + progname, port, strerror(-rc)); + close(fd); + return -1; + } + return 0; +} + + +static void ser_close(union filedescriptor *fd) +{ + /* + * restore original termios settings from ser_open + */ + if (saved_original_termios) { + int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &original_termios); + if (rc) { + fprintf(stderr, + "%s: ser_close(): can't reset attributes for device: %s\n", + progname, strerror(errno)); + } + saved_original_termios = 0; + } + + close(fd->ifd); +} + + +static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen) +{ + struct timeval timeout, to2; + int rc; + unsigned char * p = buf; + size_t len = buflen; + + if (!len) + return 0; + + if (verbose > 3) + { + fprintf(stderr, "%s: Send: ", progname); + + while (buflen) { + unsigned char c = *buf; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + buf++; + buflen--; + } + + fprintf(stderr, "\n"); + } + + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + to2 = timeout; + + while (len) { + rc = write(fd->ifd, p, (len > 1024) ? 1024 : len); + if (rc < 0) { + fprintf(stderr, "%s: ser_send(): write error: %s\n", + progname, strerror(errno)); + exit(1); + } + p += rc; + len -= rc; + } + + return 0; +} + + +static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen) +{ + struct timeval timeout, to2; + fd_set rfds; + int nfds; + int rc; + unsigned char * p = buf; + size_t len = 0; + + timeout.tv_sec = serial_recv_timeout / 1000L; + timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000; + to2 = timeout; + + while (len < buflen) { + reselect: + FD_ZERO(&rfds); + FD_SET(fd->ifd, &rfds); + + nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2); + if (nfds == 0) { + if (verbose > 1) + fprintf(stderr, + "%s: ser_recv(): programmer is not responding\n", + progname); + return -1; + } + else if (nfds == -1) { + if (errno == EINTR || errno == EAGAIN) { + fprintf(stderr, + "%s: ser_recv(): programmer is not responding,reselecting\n", + progname); + goto reselect; + } + else { + fprintf(stderr, "%s: ser_recv(): select(): %s\n", + progname, strerror(errno)); + exit(1); + } + } + + rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len); + if (rc < 0) { + fprintf(stderr, "%s: ser_recv(): read error: %s\n", + progname, strerror(errno)); + exit(1); + } + p += rc; + len += rc; + } + + p = buf; + + if (verbose > 3) + { + fprintf(stderr, "%s: Recv: ", progname); + + while (len) { + unsigned char c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + len--; + } + fprintf(stderr, "\n"); + } + + return 0; +} + + +static int ser_drain(union filedescriptor *fd, int display) +{ + struct timeval timeout; + fd_set rfds; + int nfds; + int rc; + unsigned char buf; + + timeout.tv_sec = 0; + timeout.tv_usec = 250000; + + if (display) { + fprintf(stderr, "drain>"); + } + + while (1) { + FD_ZERO(&rfds); + FD_SET(fd->ifd, &rfds); + + reselect: + nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout); + if (nfds == 0) { + if (display) { + fprintf(stderr, "ifd, &buf, 1); + if (rc < 0) { + fprintf(stderr, "%s: ser_drain(): read error: %s\n", + progname, strerror(errno)); + exit(1); + } + if (display) { + fprintf(stderr, "%02x ", buf); + } + } + + return 0; +} + +struct serial_device serial_serdev = +{ + .open = ser_open, + .setspeed = ser_setspeed, + .close = ser_close, + .send = ser_send, + .recv = ser_recv, + .drain = ser_drain, + .set_dtr_rts = ser_set_dtr_rts, + .flags = SERDEV_FL_CANSETSPEED, +}; + +struct serial_device *serdev = &serial_serdev; + +#endif /* WIN32NATIVE */ diff --git a/avrdude/ser_win32.c b/avrdude/ser_win32.c new file mode 100644 index 00000000..4b55646b --- /dev/null +++ b/avrdude/ser_win32.c @@ -0,0 +1,408 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003, 2004 Martin J. Thomas + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Native Win32 serial interface for avrdude. + */ + +#include "avrdude.h" + +#if defined(WIN32NATIVE) + +#include +#include +#include /* for isprint */ + +#include "serial.h" + +long serial_recv_timeout = 5000; /* ms */ + +#define W32SERBUFSIZE 1024 + +struct baud_mapping { + long baud; + DWORD speed; +}; + +/* HANDLE hComPort=INVALID_HANDLE_VALUE; */ + +static struct baud_mapping baud_lookup_table [] = { + { 1200, CBR_1200 }, + { 2400, CBR_2400 }, + { 4800, CBR_4800 }, + { 9600, CBR_9600 }, + { 19200, CBR_19200 }, + { 38400, CBR_38400 }, + { 57600, CBR_57600 }, + { 115200, CBR_115200 }, + { 0, 0 } /* Terminator. */ +}; + +static DWORD serial_baud_lookup(long baud) +{ + struct baud_mapping *map = baud_lookup_table; + + while (map->baud) { + if (map->baud == baud) + return map->speed; + map++; + } + + /* + * If a non-standard BAUD rate is used, issue + * a warning (if we are verbose) and return the raw rate + */ + if (verbose > 0) + fprintf(stderr, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld", + progname, baud); + + return baud; +} + + +static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms +{ + COMMTIMEOUTS ctmo; + ZeroMemory (&ctmo, sizeof(COMMTIMEOUTS)); + ctmo.ReadIntervalTimeout = timeout; + ctmo.ReadTotalTimeoutMultiplier = timeout; + ctmo.ReadTotalTimeoutConstant = timeout; + + return SetCommTimeouts(hComPort, &ctmo); +} + +static int ser_setspeed(union filedescriptor *fd, long baud) +{ + DCB dcb; + HANDLE hComPort = (HANDLE)fd->pfd; + + ZeroMemory (&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = serial_baud_lookup (baud); + dcb.fBinary = 1; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + + if (!SetCommState(hComPort, &dcb)) + return -1; + + return 0; +} + + +static int ser_open(char * port, long baud, union filedescriptor *fdp) +{ + LPVOID lpMsgBuf; + HANDLE hComPort=INVALID_HANDLE_VALUE; + char *newname = 0; + + /* + * If the port is of the form "net::", then + * handle it as a TCP connection to a terminal server. + * + * This is curently not implemented for Win32. + */ + if (strncmp(port, "net:", strlen("net:")) == 0) { + fprintf(stderr, + "%s: ser_open(): network connects are currently not" + "implemented for Win32 environments\n", + progname); + return -1; + } + + if (strncasecmp(port, "com", strlen("com")) == 0) { + + // prepend "\\\\.\\" to name, required for port # >= 10 + newname = malloc(strlen("\\\\.\\") + strlen(port) + 1); + + if (newname == 0) { + fprintf(stderr, + "%s: ser_open(): out of memory\n", + progname); + exit(1); + } + strcpy(newname, "\\\\.\\"); + strcat(newname, port); + + port = newname; + } + + hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hComPort == INVALID_HANDLE_VALUE) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n", + progname, port, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + return -1; + } + + if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set buffers for \"%s\"\n", + progname, port); + return -1; + } + + fdp->pfd = (void *)hComPort; + if (ser_setspeed(fdp, baud) != 0) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set com-state for \"%s\"\n", + progname, port); + return -1; + } + + if (!serial_w32SetTimeOut(hComPort,0)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set initial timeout for \"%s\"\n", + progname, port); + return -1; + } + + if (newname != 0) { + free(newname); + } + return 0; +} + + +static void ser_close(union filedescriptor *fd) +{ + HANDLE hComPort=(HANDLE)fd->pfd; + if (hComPort != INVALID_HANDLE_VALUE) + CloseHandle (hComPort); + + hComPort = INVALID_HANDLE_VALUE; +} + +static int ser_set_dtr_rts(union filedescriptor *fd, int is_on) +{ + HANDLE hComPort=(HANDLE)fd->pfd; + + if (is_on) { + EscapeCommFunction(hComPort, SETDTR); + EscapeCommFunction(hComPort, SETRTS); + } else { + EscapeCommFunction(hComPort, CLRDTR); + EscapeCommFunction(hComPort, CLRRTS); + } + return 0; +} + + +static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen) +{ + size_t len = buflen; + unsigned char c='\0'; + DWORD written; + unsigned char * b = buf; + + HANDLE hComPort=(HANDLE)fd->pfd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: ser_send(): port not open\n", + progname); + exit(1); + } + + if (!len) + return 0; + + if (verbose > 3) + { + fprintf(stderr, "%s: Send: ", progname); + + while (len) { + c = *b; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + b++; + len--; + } + fprintf(stderr, "\n"); + } + + serial_w32SetTimeOut(hComPort,500); + + if (!WriteFile (hComPort, buf, buflen, &written, NULL)) { + fprintf(stderr, "%s: ser_send(): write error: %s\n", + progname, "sorry no info avail"); // TODO + exit(1); + } + + if (written != buflen) { + fprintf(stderr, "%s: ser_send(): size/send mismatch\n", + progname); + exit(1); + } + + return 0; +} + + +static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen) +{ + unsigned char c; + unsigned char * p = buf; + DWORD read; + + HANDLE hComPort=(HANDLE)fd->pfd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: ser_read(): port not open\n", + progname); + exit(1); + } + + serial_w32SetTimeOut(hComPort, serial_recv_timeout); + + if (!ReadFile(hComPort, buf, buflen, &read, NULL)) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + fprintf(stderr, "%s: ser_recv(): read error: %s\n", + progname, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + p = buf; + + if (verbose > 3) + { + fprintf(stderr, "%s: Recv: ", progname); + + while (read) { + c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + read--; + } + fprintf(stderr, "\n"); + } + return 0; +} + + +static int ser_drain(union filedescriptor *fd, int display) +{ + // int rc; + unsigned char buf[10]; + BOOL readres; + DWORD read; + + HANDLE hComPort=(HANDLE)fd->pfd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: ser_drain(): port not open\n", + progname); + exit(1); + } + + serial_w32SetTimeOut(hComPort,250); + + if (display) { + fprintf(stderr, "drain>"); + } + + while (1) { + readres=ReadFile(hComPort, buf, 1, &read, NULL); + if (!readres) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + fprintf(stderr, "%s: ser_drain(): read error: %s\n", + progname, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + if (read) { // data avail + if (display) fprintf(stderr, "%02x ", buf[0]); + } + else { // no more data + if (display) fprintf(stderr, " + * Copyright (C) 2005 Michael Holzt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* $Id$ */ + +#ifndef serbb_h +#define serbb_h + +#ifdef __cplusplus +extern "C" { +#endif + +void serbb_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/avrdude/serbb_posix.c b/avrdude/serbb_posix.c new file mode 100644 index 00000000..668a2079 --- /dev/null +++ b/avrdude/serbb_posix.c @@ -0,0 +1,313 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean + * Copyright (C) 2005 Michael Holzt + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* $Id$ */ + +/* + * Posix serial bitbanging interface for avrdude. + */ + +#if !defined(WIN32NATIVE) + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" +#include "bitbang.h" + +#undef DEBUG + +static struct termios oldmode; + +/* + serial port/pin mapping + + 1 cd <- + 2 (rxd) <- + 3 txd -> + 4 dtr -> + 5 GND + 6 dsr <- + 7 rts -> + 8 cts <- + 9 ri <- +*/ + +#define DB9PINS 9 + +static int serregbits[DB9PINS + 1] = +{ 0, TIOCM_CD, 0, 0, TIOCM_DTR, 0, TIOCM_DSR, TIOCM_RTS, TIOCM_CTS, TIOCM_RI }; + +#ifdef DEBUG +static char *serpins[DB9PINS + 1] = + { "NONE", "CD", "RXD", "TXD", "DTR", "GND", "DSR", "RTS", "CTS", "RI" }; +#endif + +static int serbb_setpin(PROGRAMMER * pgm, int pin, int value) +{ + unsigned int ctl; + int r; + + if (pin & PIN_INVERSE) + { + value = !value; + pin &= PIN_MASK; + } + + if ( pin < 1 || pin > DB9PINS ) + return -1; + +#ifdef DEBUG + printf("%s to %d\n",serpins[pin],value); +#endif + + switch ( pin ) + { + case 3: /* txd */ + r = ioctl(pgm->fd.ifd, value ? TIOCSBRK : TIOCCBRK, 0); + if (r < 0) { + perror("ioctl(\"TIOCxBRK\")"); + return -1; + } + break; + + case 4: /* dtr */ + case 7: /* rts */ + r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMGET\")"); + return -1; + } + if ( value ) + ctl |= serregbits[pin]; + else + ctl &= ~(serregbits[pin]); + r = ioctl(pgm->fd.ifd, TIOCMSET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMSET\")"); + return -1; + } + break; + + default: /* impossible */ + return -1; + } + + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + + return 0; +} + +static int serbb_getpin(PROGRAMMER * pgm, int pin) +{ + unsigned int ctl; + unsigned char invert; + int r; + + if (pin & PIN_INVERSE) + { + invert = 1; + pin &= PIN_MASK; + } else + invert = 0; + + if ( pin < 1 || pin > DB9PINS ) + return(-1); + + switch ( pin ) + { + case 2: /* rxd, currently not implemented, FIXME */ + return(-1); + + case 1: /* cd */ + case 6: /* dsr */ + case 8: /* cts */ + case 9: /* ri */ + r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMGET\")"); + return -1; + } + if ( !invert ) + { +#ifdef DEBUG + printf("%s is %d\n",serpins[pin],(ctl & serregbits[pin]) ? 1 : 0 ); +#endif + return ( (ctl & serregbits[pin]) ? 1 : 0 ); + } + else + { +#ifdef DEBUG + printf("%s is %d (~)\n",serpins[pin],(ctl & serregbits[pin]) ? 0 : 1 ); +#endif + return (( ctl & serregbits[pin]) ? 0 : 1 ); + } + + default: /* impossible */ + return(-1); + } +} + +static int serbb_highpulsepin(PROGRAMMER * pgm, int pin) +{ + if ( (pin & PIN_MASK) < 1 || (pin & PIN_MASK) > DB9PINS ) + return -1; + + serbb_setpin(pgm, pin, 1); + serbb_setpin(pgm, pin, 0); + + return 0; +} + + + +static void serbb_display(PROGRAMMER *pgm, const char *p) +{ + /* MAYBE */ +} + +static void serbb_enable(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static void serbb_disable(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static void serbb_powerup(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static void serbb_powerdown(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static int serbb_open(PROGRAMMER *pgm, char *port) +{ + struct termios mode; + int flags; + int r; + + bitbang_check_prerequisites(pgm); + + /* adapted from uisp code */ + + pgm->fd.ifd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK); + + if (pgm->fd.ifd < 0) { + perror(port); + return(-1); + } + + r = tcgetattr(pgm->fd.ifd, &mode); + if (r < 0) { + fprintf(stderr, "%s: ", port); + perror("tcgetattr"); + return(-1); + } + oldmode = mode; + + mode.c_iflag = IGNBRK | IGNPAR; + mode.c_oflag = 0; + mode.c_cflag = CLOCAL | CREAD | CS8 | B9600; + mode.c_cc [VMIN] = 1; + mode.c_cc [VTIME] = 0; + + r = tcsetattr(pgm->fd.ifd, TCSANOW, &mode); + if (r < 0) { + fprintf(stderr, "%s: ", port); + perror("tcsetattr"); + return(-1); + } + + /* Clear O_NONBLOCK flag. */ + flags = fcntl(pgm->fd.ifd, F_GETFL, 0); + if (flags == -1) + { + fprintf(stderr, "%s: Can not get flags: %s\n", + progname, strerror(errno)); + return(-1); + } + flags &= ~O_NONBLOCK; + if (fcntl(pgm->fd.ifd, F_SETFL, flags) == -1) + { + fprintf(stderr, "%s: Can not clear nonblock flag: %s\n", + progname, strerror(errno)); + return(-1); + } + + return(0); +} + +static void serbb_close(PROGRAMMER *pgm) +{ + if (pgm->fd.ifd != -1) + { + (void)tcsetattr(pgm->fd.ifd, TCSANOW, &oldmode); + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); + close(pgm->fd.ifd); + } + return; +} + +void serbb_initpgm(PROGRAMMER *pgm) +{ + strcpy(pgm->type, "SERBB"); + + pgm->rdy_led = bitbang_rdy_led; + pgm->err_led = bitbang_err_led; + pgm->pgm_led = bitbang_pgm_led; + pgm->vfy_led = bitbang_vfy_led; + pgm->initialize = bitbang_initialize; + pgm->display = serbb_display; + pgm->enable = serbb_enable; + pgm->disable = serbb_disable; + pgm->powerup = serbb_powerup; + pgm->powerdown = serbb_powerdown; + pgm->program_enable = bitbang_program_enable; + pgm->chip_erase = bitbang_chip_erase; + pgm->cmd = bitbang_cmd; + pgm->cmd_tpi = bitbang_cmd_tpi; + pgm->open = serbb_open; + pgm->close = serbb_close; + pgm->setpin = serbb_setpin; + pgm->getpin = serbb_getpin; + pgm->highpulsepin = serbb_highpulsepin; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; +} + +#endif /* WIN32NATIVE */ diff --git a/avrdude/serbb_win32.c b/avrdude/serbb_win32.c new file mode 100644 index 00000000..2f5af8ad --- /dev/null +++ b/avrdude/serbb_win32.c @@ -0,0 +1,374 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003, 2004 Martin J. Thomas + * Copyright (C) 2005 Michael Holzt + * Copyright (C) 2005, 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* $Id$ */ + +/* + * Win32 serial bitbanging interface for avrdude. + */ + +#include "avrdude.h" + +#if defined(WIN32NATIVE) + + +#include "ac_cfg.h" + +#include +#include + +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" +#include "bitbang.h" + +/* cached status lines */ +static int dtr, rts, txd; + +#define W32SERBUFSIZE 1024 + +/* + serial port/pin mapping + + 1 cd <- + 2 (rxd) <- + 3 txd -> + 4 dtr -> + 5 GND + 6 dsr <- + 7 rts -> + 8 cts <- + 9 ri <- +*/ + +#define DB9PINS 9 + +static int serbb_setpin(PROGRAMMER * pgm, int pin, int value) +{ + HANDLE hComPort = (HANDLE)pgm->fd.pfd; + LPVOID lpMsgBuf; + DWORD dwFunc; + const char *name; + + if (pin & PIN_INVERSE) + { + value = !value; + pin &= PIN_MASK; + } + + if (pin < 1 || pin > DB9PINS) + return -1; + + switch (pin) + { + case 3: /* txd */ + dwFunc = value? SETBREAK: CLRBREAK; + name = value? "SETBREAK": "CLRBREAK"; + txd = value; + break; + + case 4: /* dtr */ + dwFunc = value? SETDTR: CLRDTR; + name = value? "SETDTR": "CLRDTR"; + dtr = value; + break; + + case 7: /* rts */ + dwFunc = value? SETRTS: CLRRTS; + name = value? "SETRTS": "CLRRTS"; + break; + + default: + if (verbose) + fprintf(stderr, + "%s: serbb_setpin(): unknown pin %d\n", + progname, pin + 1); + return -1; + } + if (verbose > 4) + fprintf(stderr, + "%s: serbb_setpin(): EscapeCommFunction(%s)\n", + progname, name); + if (!EscapeCommFunction(hComPort, dwFunc)) + { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + fprintf(stderr, + "%s: serbb_setpin(): SetCommState() failed: %s\n", + progname, (char *)lpMsgBuf); + CloseHandle(hComPort); + LocalFree(lpMsgBuf); + exit(1); + } + + if (pgm->ispdelay > 1) + bitbang_delay(pgm->ispdelay); + + return 0; +} + +static int serbb_getpin(PROGRAMMER * pgm, int pin) +{ + HANDLE hComPort = (HANDLE)pgm->fd.pfd; + LPVOID lpMsgBuf; + int invert, rv; + const char *name; + DWORD modemstate; + + if (pin & PIN_INVERSE) + { + invert = 1; + pin &= PIN_MASK; + } else + invert = 0; + + if (pin < 1 || pin > DB9PINS) + return -1; + + if (pin == 1 /* cd */ || pin == 6 /* dsr */ || pin == 8 /* cts */) + { + if (!GetCommModemStatus(hComPort, &modemstate)) + { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + fprintf(stderr, + "%s: serbb_setpin(): GetCommModemStatus() failed: %s\n", + progname, (char *)lpMsgBuf); + CloseHandle(hComPort); + LocalFree(lpMsgBuf); + exit(1); + } + if (verbose > 4) + fprintf(stderr, + "%s: serbb_getpin(): GetCommState() => 0x%lx\n", + progname, modemstate); + switch (pin) + { + case 1: + modemstate &= MS_RLSD_ON; + break; + case 6: + modemstate &= MS_DSR_ON; + break; + case 8: + modemstate &= MS_CTS_ON; + break; + } + rv = modemstate != 0; + if (invert) + rv = !rv; + + return rv; + } + + switch (pin) + { + case 3: /* txd */ + rv = txd; + name = "TXD"; + break; + case 4: /* dtr */ + rv = dtr; + name = "DTR"; + break; + case 7: /* rts */ + rv = rts; + name = "RTS"; + break; + default: + if (verbose) + fprintf(stderr, + "%s: serbb_getpin(): unknown pin %d\n", + progname, pin + 1); + return -1; + } + if (verbose > 4) + fprintf(stderr, + "%s: serbb_getpin(): return cached state for %s\n", + progname, name); + if (invert) + rv = !rv; + + return rv; +} + +static int serbb_highpulsepin(PROGRAMMER * pgm, int pin) +{ + if ( (pin & PIN_MASK) < 1 || (pin & PIN_MASK) > DB9PINS ) + return -1; + + serbb_setpin(pgm, pin, 1); + serbb_setpin(pgm, pin, 0); + + return 0; +} + + +static void serbb_display(PROGRAMMER *pgm, const char *p) +{ + /* MAYBE */ +} + +static void serbb_enable(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static void serbb_disable(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static void serbb_powerup(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static void serbb_powerdown(PROGRAMMER *pgm) +{ + /* nothing */ +} + +static int serbb_open(PROGRAMMER *pgm, char *port) +{ + DCB dcb; + LPVOID lpMsgBuf; + HANDLE hComPort = INVALID_HANDLE_VALUE; + + bitbang_check_prerequisites(pgm); + + hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hComPort == INVALID_HANDLE_VALUE) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n", + progname, port, (char*)lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set buffers for \"%s\"\n", + progname, port); + return -1; + } + + + ZeroMemory(&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = CBR_9600; + dcb.fBinary = 1; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + + if (!SetCommState(hComPort, &dcb)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set com-state for \"%s\"\n", + progname, port); + return -1; + } + if (verbose > 2) + fprintf(stderr, + "%s: ser_open(): opened comm port \"%s\", handle 0x%x\n", + progname, port, (int)hComPort); + + pgm->fd.pfd = (void *)hComPort; + + dtr = rts = txd = 0; + + return 0; +} + +static void serbb_close(PROGRAMMER *pgm) +{ + HANDLE hComPort=(HANDLE)pgm->fd.pfd; + if (hComPort != INVALID_HANDLE_VALUE) + { + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); + CloseHandle (hComPort); + } + if (verbose > 2) + fprintf(stderr, + "%s: ser_close(): closed comm port handle 0x%x\n", + progname, (int)hComPort); + + hComPort = INVALID_HANDLE_VALUE; +} + +void serbb_initpgm(PROGRAMMER *pgm) +{ + strcpy(pgm->type, "SERBB"); + + pgm->rdy_led = bitbang_rdy_led; + pgm->err_led = bitbang_err_led; + pgm->pgm_led = bitbang_pgm_led; + pgm->vfy_led = bitbang_vfy_led; + pgm->initialize = bitbang_initialize; + pgm->display = serbb_display; + pgm->enable = serbb_enable; + pgm->disable = serbb_disable; + pgm->powerup = serbb_powerup; + pgm->powerdown = serbb_powerdown; + pgm->program_enable = bitbang_program_enable; + pgm->chip_erase = bitbang_chip_erase; + pgm->cmd = bitbang_cmd; + pgm->cmd_tpi = bitbang_cmd_tpi; + pgm->open = serbb_open; + pgm->close = serbb_close; + pgm->setpin = serbb_setpin; + pgm->getpin = serbb_getpin; + pgm->highpulsepin = serbb_highpulsepin; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; +} + +#endif /* WIN32NATIVE */ diff --git a/avrdude/serial.h b/avrdude/serial.h new file mode 100644 index 00000000..edb352a9 --- /dev/null +++ b/avrdude/serial.h @@ -0,0 +1,77 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003-2004 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* This is the API for the generic serial interface. The implementations are + actually provided by the target dependant files: + + ser_posix.c : posix serial interface. + ser_win32.c : native win32 serial interface. + + The target file will be selected at configure time. */ + +#ifndef serial_h +#define serial_h + +extern long serial_recv_timeout; +union filedescriptor +{ + int ifd; + void *pfd; + struct + { + void *handle; + int ep; + } usb; +}; + +struct serial_device +{ + // open should return -1 on error, other values on success + int (*open)(char * port, long baud, union filedescriptor *fd); + int (*setspeed)(union filedescriptor *fd, long baud); + void (*close)(union filedescriptor *fd); + + int (*send)(union filedescriptor *fd, unsigned char * buf, size_t buflen); + int (*recv)(union filedescriptor *fd, unsigned char * buf, size_t buflen); + int (*drain)(union filedescriptor *fd, int display); + + int (*set_dtr_rts)(union filedescriptor *fd, int is_on); + + int flags; +#define SERDEV_FL_NONE 0x0000 /* no flags */ +#define SERDEV_FL_CANSETSPEED 0x0001 /* device can change speed */ +}; + +extern struct serial_device *serdev; +extern struct serial_device serial_serdev; +extern struct serial_device usb_serdev; +extern struct serial_device usb_serdev_frame; +extern struct serial_device avrdoper_serdev; + +#define serial_open (serdev->open) +#define serial_setspeed (serdev->setspeed) +#define serial_close (serdev->close) +#define serial_send (serdev->send) +#define serial_recv (serdev->recv) +#define serial_drain (serdev->drain) +#define serial_set_dtr_rts (serdev->set_dtr_rts) + +#endif /* serial_h */ diff --git a/avrdude/solaris_ecpp.h b/avrdude/solaris_ecpp.h new file mode 100644 index 00000000..b6812439 --- /dev/null +++ b/avrdude/solaris_ecpp.h @@ -0,0 +1,51 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef solaris_ecpp_h +#define solaris_ecpp_h + +#include + +#define ppi_claim(fd) \ + do { \ + struct ecpp_transfer_parms p; \ + (void)ioctl(fd, ECPPIOC_GETPARMS, &p); \ + p.mode = ECPP_DIAG_MODE; \ + (void)ioctl(fd, ECPPIOC_SETPARMS, &p); \ + } while(0); + +#define ppi_release(fd) + +#define DO_PPI_READ(fd, reg, valp) \ + do { struct ecpp_regs r; \ + if ((reg) == PPIDATA) { (void)ioctl(fd, ECPPIOC_GETDATA, valp); } \ + else { (void)ioctl(fd, ECPPIOC_GETREGS, &r); \ + *(valp) = ((reg) == PPICTRL)? r.dcr: r.dsr; } \ + } while(0) +#define DO_PPI_WRITE(fd, reg, valp) \ + do { struct ecpp_regs r; \ + if ((reg) == PPIDATA) { (void)ioctl(fd, ECPPIOC_SETDATA, valp); } \ + else { if ((reg) == PPICTRL) r.dcr = *(valp); else r.dsr = *(valp); \ + (void)ioctl(fd, ECPPIOC_SETREGS, &r); } \ + } while(0) + + +#endif /* solaris_ecpp_h */ diff --git a/avrdude/stk500.c b/avrdude/stk500.c new file mode 100644 index 00000000..08050440 --- /dev/null +++ b/avrdude/stk500.c @@ -0,0 +1,1364 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004 Brian S. Dean + * Copyright (C) 2008 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel STK500 programmer + * + * Note: most commands use the "universal command" feature of the + * programmer in a "pass through" mode, exceptions are "program + * enable", "paged read", and "paged write". + * + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "stk500_private.h" +#include "serial.h" + +#define STK500_XTAL 7372800U + +static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value); +static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value); +static void stk500_print_parms1(PROGRAMMER * pgm, const char * p); +static int stk500_is_page_empty(unsigned int address, int page_size, + const unsigned char *buf); + + +static int stk500_send(PROGRAMMER * pgm, unsigned char * buf, size_t len) +{ + return serial_send(&pgm->fd, buf, len); +} + + +static int stk500_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len) +{ + int rv; + + rv = serial_recv(&pgm->fd, buf, len); + if (rv < 0) { + fprintf(stderr, + "%s: stk500_recv(): programmer is not responding\n", + progname); + return -1; + } + return 0; +} + + +int stk500_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(&pgm->fd, display); +} + + +int stk500_getsync(PROGRAMMER * pgm) +{ + unsigned char buf[32], resp[32]; + + /* + * get in sync */ + buf[0] = Cmnd_STK_GET_SYNC; + buf[1] = Sync_CRC_EOP; + + /* + * First send and drain a few times to get rid of line noise + */ + + stk500_send(pgm, buf, 2); + stk500_drain(pgm, 0); + stk500_send(pgm, buf, 2); + stk500_drain(pgm, 0); + + stk500_send(pgm, buf, 2); + if (stk500_recv(pgm, resp, 1) < 0) + return -1; + if (resp[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: stk500_getsync(): not in sync: resp=0x%02x\n", + progname, resp[0]); + stk500_drain(pgm, 0); + return -1; + } + + if (stk500_recv(pgm, resp, 1) < 0) + return -1; + if (resp[0] != Resp_STK_OK) { + fprintf(stderr, + "%s: stk500_getsync(): can't communicate with device: " + "resp=0x%02x\n", + progname, resp[0]); + return -1; + } + + return 0; +} + + +/* + * transmit an AVR device command and return the results; 'cmd' and + * 'res' must point to at least a 4 byte data buffer + */ +static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + unsigned char buf[32]; + + buf[0] = Cmnd_STK_UNIVERSAL; + buf[1] = cmd[0]; + buf[2] = cmd[1]; + buf[3] = cmd[2]; + buf[4] = cmd[3]; + buf[5] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 6); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, "%s: stk500_cmd(): programmer is out of sync\n", progname); + exit(1); + } + + res[0] = cmd[1]; + res[1] = cmd[2]; + res[2] = cmd[3]; + if (stk500_recv(pgm, &res[3], 1) < 0) + exit(1); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] != Resp_STK_OK) { + fprintf(stderr, "%s: stk500_cmd(): protocol error\n", progname); + exit(1); + } + + return 0; +} + + + +/* + * issue the 'chip erase' command to the AVR device + */ +static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + if (pgm->cmd == NULL) { + fprintf(stderr, + "%s: Error: %s programmer uses stk500_chip_erase() but does not\n" + "provide a cmd() method.\n", + progname, pgm->type); + return -1; + } + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return 0; +} + +/* + * issue the 'program enable' command to the AVR device + */ +static int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[16]; + int tries=0; + + retry: + + tries++; + + buf[0] = Cmnd_STK_ENTER_PROGMODE; + buf[1] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 2); + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "%s: stk500_program_enable(): can't get into sync\n", + progname); + return -1; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: stk500_program_enable(): protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -1; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_OK) { + return 0; + } + else if (buf[0] == Resp_STK_NODEVICE) { + fprintf(stderr, "%s: stk500_program_enable(): no device\n", + progname); + return -1; + } + + if(buf[0] == Resp_STK_FAILED) + { + fprintf(stderr, + "%s: stk500_program_enable(): failed to enter programming mode\n", + progname); + return -1; + } + + + fprintf(stderr, "%s: stk500_program_enable(): unknown response=0x%02x\n", + progname, buf[0]); + + return -1; +} + + + +static int stk500_set_extended_parms(PROGRAMMER * pgm, int n, + unsigned char * cmd) +{ + unsigned char buf[16]; + int tries=0; + int i; + + retry: + + tries++; + + buf[0] = Cmnd_STK_SET_DEVICE_EXT; + for (i=0; i 33) { + fprintf(stderr, "%s: stk500_set_extended_parms(): can't get into sync\n", + progname); + return -1; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: stk500_set_extended_parms(): protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -1; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_OK) { + return 0; + } + else if (buf[0] == Resp_STK_NODEVICE) { + fprintf(stderr, "%s: stk500_set_extended_parms(): no device\n", + progname); + return -1; + } + + if(buf[0] == Resp_STK_FAILED) + { + fprintf(stderr, + "%s: stk500_set_extended_parms(): failed to set extended " + "device programming parameters\n", + progname); + return -1; + } + + + fprintf(stderr, "%s: stk500_set_extended_parms(): unknown response=0x%02x\n", + progname, buf[0]); + + return -1; +} + +/* + * Crossbow MIB510 initialization and shutdown. Use cmd = 1 to + * initialize, cmd = 0 to close. + */ +static int mib510_isp(PROGRAMMER * pgm, unsigned char cmd) +{ + unsigned char buf[9]; + int tries = 0; + + buf[0] = 0xaa; + buf[1] = 0x55; + buf[2] = 0x55; + buf[3] = 0xaa; + buf[4] = 0x17; + buf[5] = 0x51; + buf[6] = 0x31; + buf[7] = 0x13; + buf[8] = cmd; + + + retry: + + tries++; + + stk500_send(pgm, buf, 9); + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "%s: mib510_isp(): can't get into sync\n", + progname); + return -1; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: mib510_isp(): protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -1; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_OK) { + return 0; + } + else if (buf[0] == Resp_STK_NODEVICE) { + fprintf(stderr, "%s: mib510_isp(): no device\n", + progname); + return -1; + } + + if (buf[0] == Resp_STK_FAILED) + { + fprintf(stderr, + "%s: mib510_isp(): command %d failed\n", + progname, cmd); + return -1; + } + + + fprintf(stderr, "%s: mib510_isp(): unknown response=0x%02x\n", + progname, buf[0]); + + return -1; +} + + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[32]; + AVRMEM * m; + int tries; + unsigned maj, min; + int rc; + int n_extparms; + + stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj); + stk500_getparm(pgm, Parm_STK_SW_MINOR, &min); + + // MIB510 does not need extparams + if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0) + n_extparms = 0; + else if ((maj > 1) || ((maj == 1) && (min > 10))) + n_extparms = 4; + else + n_extparms = 3; + + tries = 0; + + retry: + tries++; + + memset(buf, 0, sizeof(buf)); + + /* + * set device programming parameters + */ + buf[0] = Cmnd_STK_SET_DEVICE; + + buf[1] = p->stk500_devcode; + buf[2] = 0; /* device revision */ + + if ((p->flags & AVRPART_SERIALOK) && (p->flags & AVRPART_PARALLELOK)) + buf[3] = 0; /* device supports parallel and serial programming */ + else + buf[3] = 1; /* device supports parallel only */ + + if (p->flags & AVRPART_PARALLELOK) { + if (p->flags & AVRPART_PSEUDOPARALLEL) { + buf[4] = 0; /* pseudo parallel interface */ + n_extparms = 0; + } + else { + buf[4] = 1; /* full parallel interface */ + } + } + +#if 0 + fprintf(stderr, "%s: stk500_initialize(): n_extparms = %d\n", + progname, n_extparms); +#endif + + buf[5] = 1; /* polling supported - XXX need this in config file */ + buf[6] = 1; /* programming is self-timed - XXX need in config file */ + + m = avr_locate_mem(p, "lock"); + if (m) + buf[7] = m->size; + else + buf[7] = 0; + + /* + * number of fuse bytes + */ + buf[8] = 0; + m = avr_locate_mem(p, "fuse"); + if (m) + buf[8] += m->size; + m = avr_locate_mem(p, "lfuse"); + if (m) + buf[8] += m->size; + m = avr_locate_mem(p, "hfuse"); + if (m) + buf[8] += m->size; + m = avr_locate_mem(p, "efuse"); + if (m) + buf[8] += m->size; + + m = avr_locate_mem(p, "flash"); + if (m) { + buf[9] = m->readback[0]; + buf[10] = m->readback[1]; + if (m->paged) { + buf[13] = (m->page_size >> 8) & 0x00ff; + buf[14] = m->page_size & 0x00ff; + } + buf[17] = (m->size >> 24) & 0xff; + buf[18] = (m->size >> 16) & 0xff; + buf[19] = (m->size >> 8) & 0xff; + buf[20] = m->size & 0xff; + } + else { + buf[9] = 0xff; + buf[10] = 0xff; + buf[13] = 0; + buf[14] = 0; + buf[17] = 0; + buf[18] = 0; + buf[19] = 0; + buf[20] = 0; + } + + m = avr_locate_mem(p, "eeprom"); + if (m) { + buf[11] = m->readback[0]; + buf[12] = m->readback[1]; + buf[15] = (m->size >> 8) & 0x00ff; + buf[16] = m->size & 0x00ff; + } + else { + buf[11] = 0xff; + buf[12] = 0xff; + buf[15] = 0; + buf[16] = 0; + } + + buf[21] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 22); + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + fprintf(stderr, + "%s: stk500_initialize(): programmer not in sync, resp=0x%02x\n", + progname, buf[0]); + if (tries > 33) + return -1; + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: stk500_initialize(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -1; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] != Resp_STK_OK) { + fprintf(stderr, + "%s: stk500_initialize(): (b) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_OK, buf[0]); + return -1; + } + + if (n_extparms) { + if ((p->pagel == 0) || (p->bs2 == 0)) { + fprintf(stderr, + "%s: please define PAGEL and BS2 signals in the configuration " + "file for part %s\n", + progname, p->desc); + } + else { + buf[0] = n_extparms+1; + + /* + * m is currently pointing to eeprom memory if the part has it + */ + if (m) + buf[1] = m->page_size; + else + buf[1] = 0; + + buf[2] = p->pagel; + buf[3] = p->bs2; + + if (n_extparms == 4) { + if (p->reset_disposition == RESET_DEDICATED) + buf[4] = 0; + else + buf[4] = 1; + } + + rc = stk500_set_extended_parms(pgm, n_extparms+1, buf); + if (rc) { + fprintf(stderr, "%s: stk500_initialize(): failed\n", progname); + exit(1); + } + } + } + + return pgm->program_enable(pgm, p); +} + + +static void stk500_disable(PROGRAMMER * pgm) +{ + unsigned char buf[16]; + int tries=0; + + retry: + + tries++; + + buf[0] = Cmnd_STK_LEAVE_PROGMODE; + buf[1] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 2); + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "%s: stk500_disable(): can't get into sync\n", + progname); + return; + } + if (stk500_getsync(pgm) < 0) + return; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: stk500_disable(): protocol error, expect=0x%02x, " + "resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_OK) { + return; + } + else if (buf[0] == Resp_STK_NODEVICE) { + fprintf(stderr, "%s: stk500_disable(): no device\n", + progname); + return; + } + + fprintf(stderr, "%s: stk500_disable(): unknown response=0x%02x\n", + progname, buf[0]); + + return; +} + +static void stk500_enable(PROGRAMMER * pgm) +{ + return; +} + + +static int stk500_open(PROGRAMMER * pgm, char * port) +{ + strcpy(pgm->port, port); + if (serial_open(port, pgm->baudrate? pgm->baudrate: 115200, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + stk500_drain(pgm, 0); + + // MIB510 init + if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0 && + mib510_isp(pgm, 1) != 0) + return -1; + + if (stk500_getsync(pgm) < 0) + return -1; + + return 0; +} + + +static void stk500_close(PROGRAMMER * pgm) +{ + // MIB510 close + if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0) + (void)mib510_isp(pgm, 0); + + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + + +static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr) +{ + unsigned char buf[16]; + int tries; + + tries = 0; + retry: + tries++; + buf[0] = Cmnd_STK_LOAD_ADDRESS; + buf[1] = addr & 0xff; + buf[2] = (addr >> 8) & 0xff; + buf[3] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 4); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "%s: stk500_loadaddr(): can't get into sync\n", + progname); + return -1; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "%s: stk500_loadaddr(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -1; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_OK) { + return 0; + } + + fprintf(stderr, + "%s: loadaddr(): (b) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + + return -1; +} + + +static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned char buf[page_size + 16]; + int memtype; + unsigned int addr; + int a_div; + int block_size; + int tries; + unsigned int n; + unsigned int i; + int flash; + + if (page_size == 0) { + // MIB510 uses page size of 256 bytes + if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0) { + page_size = 256; + } + else { + page_size = 128; + } + } + + if (strcmp(m->desc, "flash") == 0) { + memtype = 'F'; + flash = 1; + } + else if (strcmp(m->desc, "eeprom") == 0) { + memtype = 'E'; + flash = 0; + } + else { + return -2; + } + + if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO])) + a_div = 2; + else + a_div = 1; + + if (n_bytes > m->size) { + n_bytes = m->size; + n = m->size; + } + else { + if ((n_bytes % page_size) != 0) { + n = n_bytes + page_size - (n_bytes % page_size); + } + else { + n = n_bytes; + } + } + +#if 0 + fprintf(stderr, + "n_bytes = %d\n" + "n = %u\n" + "a_div = %d\n" + "page_size = %d\n", + n_bytes, n, a_div, page_size); +#endif + + for (addr = 0; addr < n; addr += page_size) { + report_progress (addr, n_bytes, NULL); + + // MIB510 uses fixed blocks size of 256 bytes + if ((strcmp(ldata(lfirst(pgm->id)), "mib510") != 0) && + (addr + page_size > n_bytes)) { + block_size = n_bytes % page_size; + } + else { + block_size = page_size; + } + + /* Only skip on empty page if programming flash. */ + if (flash) { + if (stk500_is_page_empty(addr, block_size, m->buf)) { + continue; + } + } + tries = 0; + retry: + tries++; + stk500_loadaddr(pgm, addr/a_div); + + /* build command block and avoid multiple send commands as it leads to a crash + of the silabs usb serial driver on mac os x */ + i = 0; + buf[i++] = Cmnd_STK_PROG_PAGE; + buf[i++] = (block_size >> 8) & 0xff; + buf[i++] = block_size & 0xff; + buf[i++] = memtype; + memcpy(&buf[i], &m->buf[addr], block_size); + i += block_size; + buf[i++] = Sync_CRC_EOP; + stk500_send( pgm, buf, i); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "\n%s: stk500_paged_write(): can't get into sync\n", + progname); + return -3; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: stk500_paged_write(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -4; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] != Resp_STK_OK) { + fprintf(stderr, + "\n%s: stk500_paged_write(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -5; + } + } + + return n_bytes; +} + +static int stk500_is_page_empty(unsigned int address, int page_size, + const unsigned char *buf) +{ + int i; + for(i = 0; i < page_size; i++) { + if(buf[address + i] != 0xFF) { + /* Page is not empty. */ + return(0); + } + } + + /* Page is empty. */ + return(1); +} + +static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned char buf[16]; + int memtype; + unsigned int addr; + int a_div; + int tries; + unsigned int n; + int block_size; + + if (strcmp(m->desc, "flash") == 0) { + memtype = 'F'; + } + else if (strcmp(m->desc, "eeprom") == 0) { + memtype = 'E'; + } + else { + return -2; + } + + if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO])) + a_div = 2; + else + a_div = 1; + + if (n_bytes > m->size) { + n_bytes = m->size; + n = m->size; + } + else { + if ((n_bytes % page_size) != 0) { + n = n_bytes + page_size - (n_bytes % page_size); + } + else { + n = n_bytes; + } + } + + for (addr = 0; addr < n; addr += page_size) { + report_progress (addr, n_bytes, NULL); + + // MIB510 uses fixed blocks size of 256 bytes + if ((strcmp(ldata(lfirst(pgm->id)), "mib510") != 0) && + (addr + page_size > n_bytes)) { + block_size = n_bytes % page_size; + } + else { + block_size = page_size; + } + + tries = 0; + retry: + tries++; + stk500_loadaddr(pgm, addr/a_div); + buf[0] = Cmnd_STK_READ_PAGE; + buf[1] = (block_size >> 8) & 0xff; + buf[2] = block_size & 0xff; + buf[3] = memtype; + buf[4] = Sync_CRC_EOP; + stk500_send(pgm, buf, 5); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "\n%s: stk500_paged_load(): can't get into sync\n", + progname); + return -3; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: stk500_paged_load(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -4; + } + + if (stk500_recv(pgm, &m->buf[addr], block_size) < 0) + exit(1); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + + if(strcmp(ldata(lfirst(pgm->id)), "mib510") == 0) { + if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: stk500_paged_load(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -5; + } + } + else { + if (buf[0] != Resp_STK_OK) { + fprintf(stderr, + "\n%s: stk500_paged_load(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_OK, buf[0]); + return -5; + } + } + } + + return n_bytes; +} + + +static int stk500_set_vtarget(PROGRAMMER * pgm, double v) +{ + unsigned uaref, utarg; + + utarg = (unsigned)((v + 0.049) * 10); + + if (stk500_getparm(pgm, Parm_STK_VADJUST, &uaref) != 0) { + fprintf(stderr, + "%s: stk500_set_vtarget(): cannot obtain V[aref]\n", + progname); + return -1; + } + + if (uaref > utarg) { + fprintf(stderr, + "%s: stk500_set_vtarget(): reducing V[aref] from %.1f to %.1f\n", + progname, uaref / 10.0, v); + if (stk500_setparm(pgm, Parm_STK_VADJUST, utarg) + != 0) + return -1; + } + return stk500_setparm(pgm, Parm_STK_VTARGET, utarg); +} + + +static int stk500_set_varef(PROGRAMMER * pgm, unsigned int chan /* unused */, + double v) +{ + unsigned uaref, utarg; + + uaref = (unsigned)((v + 0.049) * 10); + + if (stk500_getparm(pgm, Parm_STK_VTARGET, &utarg) != 0) { + fprintf(stderr, + "%s: stk500_set_varef(): cannot obtain V[target]\n", + progname); + return -1; + } + + if (uaref > utarg) { + fprintf(stderr, + "%s: stk500_set_varef(): V[aref] must not be greater than " + "V[target] = %.1f\n", + progname, utarg / 10.0); + return -1; + } + return stk500_setparm(pgm, Parm_STK_VADJUST, uaref); +} + + +static int stk500_set_fosc(PROGRAMMER * pgm, double v) +{ + unsigned prescale, cmatch, fosc; + static unsigned ps[] = { + 1, 8, 32, 64, 128, 256, 1024 + }; + int idx, rc; + + prescale = cmatch = 0; + if (v > 0.0) { + if (v > STK500_XTAL / 2) { + const char *unit; + if (v > 1e6) { + v /= 1e6; + unit = "MHz"; + } else if (v > 1e3) { + v /= 1e3; + unit = "kHz"; + } else + unit = "Hz"; + fprintf(stderr, + "%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n", + progname, v, unit, STK500_XTAL / 2e6); + fosc = STK500_XTAL / 2; + } else + fosc = (unsigned)v; + + for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { + if (fosc >= STK500_XTAL / (256 * ps[idx] * 2)) { + /* this prescaler value can handle our frequency */ + prescale = idx + 1; + cmatch = (unsigned)(STK500_XTAL / (2 * fosc * ps[idx])) - 1; + break; + } + } + if (idx == sizeof(ps) / sizeof(ps[0])) { + fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n", + progname, fosc, STK500_XTAL / (256 * 1024 * 2)); + return -1; + } + } + + if ((rc = stk500_setparm(pgm, Parm_STK_OSC_PSCALE, prescale)) != 0 + || (rc = stk500_setparm(pgm, Parm_STK_OSC_CMATCH, cmatch)) != 0) + return rc; + + return 0; +} + + +/* This code assumes that each count of the SCK duration parameter + represents 8/f, where f is the clock frequency of the STK500 master + processors (not the target). This number comes from Atmel + application note AVR061. It appears that the STK500 bit bangs SCK. + For small duration values, the actual SCK width is larger than + expected. As the duration value increases, the SCK width error + diminishes. */ +static int stk500_set_sck_period(PROGRAMMER * pgm, double v) +{ + int dur; + double min, max; + + min = 8.0 / STK500_XTAL; + max = 255 * min; + dur = v / min + 0.5; + + if (v < min) { + dur = 1; + fprintf(stderr, + "%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n", + progname, v / 1e-6, dur * min / 1e-6); + } else if (v > max) { + dur = 255; + fprintf(stderr, + "%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n", + progname, v / 1e-6, dur * min / 1e-6); + } + + return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur); +} + + +static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value) +{ + unsigned char buf[16]; + unsigned v; + int tries = 0; + + retry: + tries++; + buf[0] = Cmnd_STK_GET_PARAMETER; + buf[1] = parm; + buf[2] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 3); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "\n%s: stk500_getparm(): can't get into sync\n", + progname); + return -1; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: stk500_getparm(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -2; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + v = buf[0]; + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_FAILED) { + fprintf(stderr, + "\n%s: stk500_getparm(): parameter 0x%02x failed\n", + progname, v); + return -3; + } + else if (buf[0] != Resp_STK_OK) { + fprintf(stderr, + "\n%s: stk500_getparm(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -3; + } + + *value = v; + + return 0; +} + + +static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value) +{ + unsigned char buf[16]; + int tries = 0; + + retry: + tries++; + buf[0] = Cmnd_STK_SET_PARAMETER; + buf[1] = parm; + buf[2] = value; + buf[3] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 4); + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "\n%s: stk500_setparm(): can't get into sync\n", + progname); + return -1; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: stk500_setparm(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -2; + } + + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_OK) + return 0; + + parm = buf[0]; /* if not STK_OK, we've been echoed parm here */ + if (stk500_recv(pgm, buf, 1) < 0) + exit(1); + if (buf[0] == Resp_STK_FAILED) { + fprintf(stderr, + "\n%s: stk500_setparm(): parameter 0x%02x failed\n", + progname, parm); + return -3; + } + else { + fprintf(stderr, + "\n%s: stk500_setparm(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -3; + } +} + + +static void stk500_display(PROGRAMMER * pgm, const char * p) +{ + unsigned maj, min, hdw, topcard; + + stk500_getparm(pgm, Parm_STK_HW_VER, &hdw); + stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj); + stk500_getparm(pgm, Parm_STK_SW_MINOR, &min); + stk500_getparm(pgm, Param_STK500_TOPCARD_DETECT, &topcard); + + fprintf(stderr, "%sHardware Version: %d\n", p, hdw); + fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min); + if (topcard < 3) { + const char *n = "Unknown"; + + switch (topcard) { + case 1: + n = "STK502"; + break; + + case 2: + n = "STK501"; + break; + } + fprintf(stderr, "%sTopcard : %s\n", p, n); + } + stk500_print_parms1(pgm, p); + + return; +} + + +static void stk500_print_parms1(PROGRAMMER * pgm, const char * p) +{ + unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration; + + stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget); + stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust); + stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale); + stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch); + stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration); + + fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0); + fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0); + fprintf(stderr, "%sOscillator : ", p); + if (osc_pscale == 0) + fprintf(stderr, "Off\n"); + else { + int prescale = 1; + double f = STK500_XTAL / 2; + const char *unit; + + switch (osc_pscale) { + case 2: prescale = 8; break; + case 3: prescale = 32; break; + case 4: prescale = 64; break; + case 5: prescale = 128; break; + case 6: prescale = 256; break; + case 7: prescale = 1024; break; + } + f /= prescale; + f /= (osc_cmatch + 1); + if (f > 1e6) { + f /= 1e6; + unit = "MHz"; + } else if (f > 1e3) { + f /= 1000; + unit = "kHz"; + } else + unit = "Hz"; + fprintf(stderr, "%.3f %s\n", f, unit); + } + fprintf(stderr, "%sSCK period : %.1f us\n", p, + sck_duration * 8.0e6 / STK500_XTAL + 0.05); + + return; +} + + +static void stk500_print_parms(PROGRAMMER * pgm) +{ + stk500_print_parms1(pgm, ""); +} + + +void stk500_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK500"); + + /* + * mandatory functions + */ + pgm->initialize = stk500_initialize; + pgm->display = stk500_display; + pgm->enable = stk500_enable; + pgm->disable = stk500_disable; + pgm->program_enable = stk500_program_enable; + pgm->chip_erase = stk500_chip_erase; + pgm->cmd = stk500_cmd; + pgm->open = stk500_open; + pgm->close = stk500_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + pgm->paged_write = stk500_paged_write; + pgm->paged_load = stk500_paged_load; + pgm->print_parms = stk500_print_parms; + pgm->set_vtarget = stk500_set_vtarget; + pgm->set_varef = stk500_set_varef; + pgm->set_fosc = stk500_set_fosc; + pgm->set_sck_period = stk500_set_sck_period; + pgm->page_size = 256; +} diff --git a/avrdude/stk500.h b/avrdude/stk500.h new file mode 100644 index 00000000..4b22ee05 --- /dev/null +++ b/avrdude/stk500.h @@ -0,0 +1,41 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef stk500_h +#define stk500_h + +#ifdef __cplusplus +extern "C" { +#endif + +void stk500_initpgm (PROGRAMMER * pgm); + +/* used by arduino.c to avoid duplicate code */ +int stk500_getsync(PROGRAMMER * pgm); +int stk500_drain(PROGRAMMER * pgm, int display); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/avrdude/stk500_private.h b/avrdude/stk500_private.h new file mode 100644 index 00000000..7efe866c --- /dev/null +++ b/avrdude/stk500_private.h @@ -0,0 +1,103 @@ +//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************ +//* +//* Title: AVR061 - STK500 Communication Protocol +//* Filename: command.h +//* Version: 1.0 +//* Last updated: 09.09.2002 +//* +//* Support E-mail: avr@atmel.com +//* +//************************************************************************** + +// *****************[ STK Message constants ]*************************** + +#define STK_SIGN_ON_MESSAGE "AVR STK" // Sign on string for Cmnd_STK_GET_SIGN_ON + +// *****************[ STK Response constants ]*************************** + +#define Resp_STK_OK 0x10 // ' ' +#define Resp_STK_FAILED 0x11 // ' ' +#define Resp_STK_UNKNOWN 0x12 // ' ' +#define Resp_STK_NODEVICE 0x13 // ' ' +#define Resp_STK_INSYNC 0x14 // ' ' +#define Resp_STK_NOSYNC 0x15 // ' ' + +#define Resp_ADC_CHANNEL_ERROR 0x16 // ' ' +#define Resp_ADC_MEASURE_OK 0x17 // ' ' +#define Resp_PWM_CHANNEL_ERROR 0x18 // ' ' +#define Resp_PWM_ADJUST_OK 0x19 // ' ' + +// *****************[ STK Special constants ]*************************** + +#define Sync_CRC_EOP 0x20 // 'SPACE' + +// *****************[ STK Command constants ]*************************** + +#define Cmnd_STK_GET_SYNC 0x30 // ' ' +#define Cmnd_STK_GET_SIGN_ON 0x31 // ' ' + +#define Cmnd_STK_SET_PARAMETER 0x40 // ' ' +#define Cmnd_STK_GET_PARAMETER 0x41 // ' ' +#define Cmnd_STK_SET_DEVICE 0x42 // ' ' +#define Cmnd_STK_SET_DEVICE_EXT 0x45 // ' ' + +#define Cmnd_STK_ENTER_PROGMODE 0x50 // ' ' +#define Cmnd_STK_LEAVE_PROGMODE 0x51 // ' ' +#define Cmnd_STK_CHIP_ERASE 0x52 // ' ' +#define Cmnd_STK_CHECK_AUTOINC 0x53 // ' ' +#define Cmnd_STK_LOAD_ADDRESS 0x55 // ' ' +#define Cmnd_STK_UNIVERSAL 0x56 // ' ' +#define Cmnd_STK_UNIVERSAL_MULTI 0x57 // ' ' + +#define Cmnd_STK_PROG_FLASH 0x60 // ' ' +#define Cmnd_STK_PROG_DATA 0x61 // ' ' +#define Cmnd_STK_PROG_FUSE 0x62 // ' ' +#define Cmnd_STK_PROG_LOCK 0x63 // ' ' +#define Cmnd_STK_PROG_PAGE 0x64 // ' ' +#define Cmnd_STK_PROG_FUSE_EXT 0x65 // ' ' + +#define Cmnd_STK_READ_FLASH 0x70 // ' ' +#define Cmnd_STK_READ_DATA 0x71 // ' ' +#define Cmnd_STK_READ_FUSE 0x72 // ' ' +#define Cmnd_STK_READ_LOCK 0x73 // ' ' +#define Cmnd_STK_READ_PAGE 0x74 // ' ' +#define Cmnd_STK_READ_SIGN 0x75 // ' ' +#define Cmnd_STK_READ_OSCCAL 0x76 // ' ' +#define Cmnd_STK_READ_FUSE_EXT 0x77 // ' ' +#define Cmnd_STK_READ_OSCCAL_EXT 0x78 // ' ' + +// *****************[ STK Parameter constants ]*************************** + +#define Parm_STK_HW_VER 0x80 // ' ' - R +#define Parm_STK_SW_MAJOR 0x81 // ' ' - R +#define Parm_STK_SW_MINOR 0x82 // ' ' - R +#define Parm_STK_LEDS 0x83 // ' ' - R/W +#define Parm_STK_VTARGET 0x84 // ' ' - R/W +#define Parm_STK_VADJUST 0x85 // ' ' - R/W +#define Parm_STK_OSC_PSCALE 0x86 // ' ' - R/W +#define Parm_STK_OSC_CMATCH 0x87 // ' ' - R/W +#define Parm_STK_RESET_DURATION 0x88 // ' ' - R/W +#define Parm_STK_SCK_DURATION 0x89 // ' ' - R/W + +#define Parm_STK_BUFSIZEL 0x90 // ' ' - R/W, Range {0..255} +#define Parm_STK_BUFSIZEH 0x91 // ' ' - R/W, Range {0..255} +#define Parm_STK_DEVICE 0x92 // ' ' - R/W, Range {0..255} +#define Parm_STK_PROGMODE 0x93 // ' ' - 'P' or 'S' +#define Parm_STK_PARAMODE 0x94 // ' ' - TRUE or FALSE +#define Parm_STK_POLLING 0x95 // ' ' - TRUE or FALSE +#define Parm_STK_SELFTIMED 0x96 // ' ' - TRUE or FALSE +#define Param_STK500_TOPCARD_DETECT 0x98 // ' ' - Detect top-card attached + +// *****************[ STK status bit definitions ]*************************** + +#define Stat_STK_INSYNC 0x01 // INSYNC status bit, '1' - INSYNC +#define Stat_STK_PROGMODE 0x02 // Programming mode, '1' - PROGMODE +#define Stat_STK_STANDALONE 0x04 // Standalone mode, '1' - SM mode +#define Stat_STK_RESET 0x08 // RESET button, '1' - Pushed +#define Stat_STK_PROGRAM 0x10 // Program button, ' 1' - Pushed +#define Stat_STK_LEDG 0x20 // Green LED status, '1' - Lit +#define Stat_STK_LEDR 0x40 // Red LED status, '1' - Lit +#define Stat_STK_LEDBLINK 0x80 // LED blink ON/OFF, '1' - Blink + + +// *****************************[ End Of COMMAND.H ]************************** diff --git a/avrdude/stk500generic.c b/avrdude/stk500generic.c new file mode 100644 index 00000000..12125393 --- /dev/null +++ b/avrdude/stk500generic.c @@ -0,0 +1,91 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel STK500 programmer + * + * This is a wrapper around the STK500[v1] and STK500v2 programmers. + * Try to select the programmer type that actually responds, and + * divert to the actual programmer implementation if successful. + */ + +#include "ac_cfg.h" + +#include +#include + +#include "avrdude.h" +#include "pgm.h" +#include "stk500.h" +#include "stk500v2.h" + +static int stk500generic_open(PROGRAMMER * pgm, char * port) +{ + stk500_initpgm(pgm); + if (pgm->open(pgm, port) >= 0) + { + fprintf(stderr, + "%s: successfully opened stk500v1 device -- please use -c stk500v1\n", + progname); + return 0; + } + + pgm->close(pgm); + + stk500v2_initpgm(pgm); + if (pgm->open(pgm, port) >= 0) + { + fprintf(stderr, + "%s: successfully opened stk500v2 device -- please use -c stk500v2\n", + progname); + return 0; + } + + fprintf(stderr, + "%s: cannot open either stk500v1 or stk500v2 programmer\n", + progname); + return -1; +} + +static void stk500generic_setup(PROGRAMMER * pgm) +{ + /* + * Only STK500v2 needs setup/teardown. + */ + stk500v2_initpgm(pgm); + pgm->setup(pgm); +} + +static void stk500generic_teardown(PROGRAMMER * pgm) +{ + stk500v2_initpgm(pgm); + pgm->teardown(pgm); +} + + +void stk500generic_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK500GENERIC"); + + pgm->open = stk500generic_open; + pgm->setup = stk500generic_setup; + pgm->teardown = stk500generic_teardown; +} diff --git a/avrdude/stk500generic.h b/avrdude/stk500generic.h new file mode 100644 index 00000000..89af83b1 --- /dev/null +++ b/avrdude/stk500generic.h @@ -0,0 +1,29 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef stk500generic_h__ +#define stk500generic_h__ + +void stk500generic_initpgm (PROGRAMMER * pgm); + +#endif + + diff --git a/avrdude/stk500v2.c b/avrdude/stk500v2.c new file mode 100644 index 00000000..276d6f58 --- /dev/null +++ b/avrdude/stk500v2.c @@ -0,0 +1,3926 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005 Erik Walthinsen + * Copyright (C) 2002-2004 Brian S. Dean + * Copyright (C) 2006 David Moore + * Copyright (C) 2006,2007,2010 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ +/* Based on Id: stk500.c,v 1.46 2004/12/22 01:52:45 bdean Exp */ + +/* + * avrdude interface for Atmel STK500V2 programmer + * + * As the AVRISP mkII device is basically an STK500v2 one that can + * only talk across USB, and that misses any kind of framing protocol, + * this is handled here as well. + * + * Note: most commands use the "universal command" feature of the + * programmer in a "pass through" mode, exceptions are "program + * enable", "paged read", and "paged write". + * + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "stk500_private.h" // temp until all code converted +#include "stk500v2_private.h" +#include "serial.h" +#include "usbdevs.h" + +/* + * We need to import enough from the JTAG ICE mkII definitions to be + * able to talk to the ICE, query some parameters etc. The macro + * JTAGMKII_PRIVATE_EXPORTED limits the amount of definitions that + * jtagmkII_private.h will export, so to avoid conflicts with those + * names that are identical to the STK500v2 ones. + */ +#include "jtagmkII.h" // public interfaces from jtagmkII.c +#define JTAGMKII_PRIVATE_EXPORTED +#include "jtagmkII_private.h" + +#define STK500V2_XTAL 7372800U + +// Timeout (in seconds) for waiting for serial response +#define SERIAL_TIMEOUT 2 + +// Retry count +#define RETRIES 5 + +#if 0 +#define DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG(...) +#endif + +#if 0 +#define DEBUGRECV(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUGRECV(...) +#endif + +enum hvmode +{ + PPMODE, HVSPMODE +}; + + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + + +/* + * Data structure for displaying STK600 routing and socket cards. + */ +struct carddata +{ + int id; + const char *name; +}; + +static const char *pgmname[] = +{ + "unknown", + "STK500", + "AVRISP", + "AVRISP mkII", + "JTAG ICE mkII", + "STK600", +}; + +struct jtagispentry +{ + unsigned char cmd; + unsigned short size; +#define SZ_READ_FLASH_EE USHRT_MAX +#define SZ_SPI_MULTI (USHRT_MAX - 1) +}; + +static const struct jtagispentry jtagispcmds[] = { + /* generic */ + { CMD_SET_PARAMETER, 2 }, + { CMD_GET_PARAMETER, 3 }, + { CMD_OSCCAL, 2 }, + { CMD_LOAD_ADDRESS, 2 }, + /* ISP mode */ + { CMD_ENTER_PROGMODE_ISP, 2 }, + { CMD_LEAVE_PROGMODE_ISP, 2 }, + { CMD_CHIP_ERASE_ISP, 2 }, + { CMD_PROGRAM_FLASH_ISP, 2 }, + { CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE }, + { CMD_PROGRAM_EEPROM_ISP, 2 }, + { CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE }, + { CMD_PROGRAM_FUSE_ISP, 3 }, + { CMD_READ_FUSE_ISP, 4 }, + { CMD_PROGRAM_LOCK_ISP, 3 }, + { CMD_READ_LOCK_ISP, 4 }, + { CMD_READ_SIGNATURE_ISP, 4 }, + { CMD_READ_OSCCAL_ISP, 4 }, + { CMD_SPI_MULTI, SZ_SPI_MULTI }, + /* all HV modes */ + { CMD_SET_CONTROL_STACK, 2 }, + /* HVSP mode */ + { CMD_ENTER_PROGMODE_HVSP, 2 }, + { CMD_LEAVE_PROGMODE_HVSP, 2 }, + { CMD_CHIP_ERASE_HVSP, 2 }, + { CMD_PROGRAM_FLASH_HVSP, 2 }, + { CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE }, + { CMD_PROGRAM_EEPROM_HVSP, 2 }, + { CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE }, + { CMD_PROGRAM_FUSE_HVSP, 2 }, + { CMD_READ_FUSE_HVSP, 3 }, + { CMD_PROGRAM_LOCK_HVSP, 2 }, + { CMD_READ_LOCK_HVSP, 3 }, + { CMD_READ_SIGNATURE_HVSP, 3 }, + { CMD_READ_OSCCAL_HVSP, 3 }, + /* PP mode */ + { CMD_ENTER_PROGMODE_PP, 2 }, + { CMD_LEAVE_PROGMODE_PP, 2 }, + { CMD_CHIP_ERASE_PP, 2 }, + { CMD_PROGRAM_FLASH_PP, 2 }, + { CMD_READ_FLASH_PP, SZ_READ_FLASH_EE }, + { CMD_PROGRAM_EEPROM_PP, 2 }, + { CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE }, + { CMD_PROGRAM_FUSE_PP, 2 }, + { CMD_READ_FUSE_PP, 3 }, + { CMD_PROGRAM_LOCK_PP, 2 }, + { CMD_READ_LOCK_PP, 3 }, + { CMD_READ_SIGNATURE_PP, 3 }, + { CMD_READ_OSCCAL_PP, 3 }, +}; + +/* + * From XML file: + + 0 + 56 + 0 + 1 + + */ +/* + * These two tables can be semi-automatically updated from + * targetboards.xml using tools/get-stk600-cards.xsl. + */ +static const struct carddata routing_cards[] = +{ + { 0x01, "STK600-RC020T-1" }, + { 0x03, "STK600-RC028T-3" }, + { 0x05, "STK600-RC040M-5" }, + { 0x08, "STK600-RC020T-8" }, + { 0x0A, "STK600-RC040M-4" }, + { 0x0C, "STK600-RC008T-2" }, + { 0x0D, "STK600-RC028M-6" }, + { 0x10, "STK600-RC064M-10" }, + { 0x11, "STK600-RC100M-11" }, + { 0x13, "STK600-RC100X-13" }, + { 0x15, "STK600-RC044X-15" }, + { 0x18, "STK600-RC100M-18" }, + { 0x19, "STK600-RCPWM-19" }, + { 0x1A, "STK600-RC064X-14" }, + { 0x1B, "STK600-RC032U-20" }, + { 0x1C, "STK600-RC014T-12" }, + { 0x1E, "STK600-RC064U-17" }, + { 0x1F, "STK600-RCuC3B0-21" }, + { 0x20, "STK600-RCPWM-22" }, + { 0x21, "STK600-RC020T-23" }, + { 0x22, "STK600-RC044M-24" }, + { 0x23, "STK600-RC044U-25" }, + { 0x24, "STK600-RCPWM-26" }, + { 0x25, "STK600-RCuC3B48-27" }, + { 0x27, "STK600-RC032M-29" }, + { 0x28, "STK600-RC044M-30" }, + { 0x29, "STK600-RC044M-31" }, + { 0x2A, "STK600-RC014T-42" }, + { 0x2B, "STK600-RC020T-43" }, + { 0x30, "STK600-RCUC3A144-32" }, + { 0x34, "STK600-RCUC3L0-34" }, + { 0x38, "STK600-RCUC3C0-36" }, + { 0x3B, "STK600-RCUC3C0-37" }, + { 0x3E, "STK600-RCUC3A144-33" }, + { 0x46, "STK600-RCuC3A100-28" }, + { 0x55, "STK600-RC064M-9" }, + { 0x88, "STK600-RCUC3C1-38" }, + { 0x8B, "STK600-RCUC3C1-39" }, + { 0xA0, "STK600-RC008T-7" }, + { 0xB8, "STK600-RCUC3C2-40" }, + { 0xBB, "STK600-RCUC3C2-41" }, +}; + +static const struct carddata socket_cards[] = +{ + { 0x01, "STK600-TQFP48" }, + { 0x02, "STK600-TQFP32" }, + { 0x03, "STK600-TQFP100" }, + { 0x04, "STK600-SOIC" }, + { 0x06, "STK600-TQFP144" }, + { 0x09, "STK600-TinyX3U" }, + { 0x0C, "STK600-TSSOP44" }, + { 0x0D, "STK600-TQFP44" }, + { 0x0E, "STK600-TQFP64-2" }, + { 0x0F, "STK600-ATMEGA2560" }, + { 0x15, "STK600-MLF64" }, + { 0x16, "STK600-ATXMEGAT0" }, + { 0x18, "QT600-ATMEGA324-QM64" }, + { 0x19, "STK600-ATMEGA128RFA1" }, + { 0x1A, "QT600-ATTINY88-QT8" }, + { 0x1B, "QT600-ATXMEGA128A1-QT16" }, + { 0x1C, "QT600-AT32UC3L-QM64" }, + { 0x1D, "STK600-HVE2" }, + { 0x1E, "STK600-ATTINY10" }, + { 0x55, "STK600-TQFP64" }, + { 0x69, "STK600-uC3-144" }, + { 0xF0, "STK600-ATXMEGA1281A1" }, + { 0xF1, "STK600-DIP" }, +}; + +static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value); +static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value); +static int stk500v2_getparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int * value); +static int stk500v2_setparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int value); +static int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned char value); +static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p); +static int stk500v2_is_page_empty(unsigned int address, int page_size, + const unsigned char *buf); + +static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize); + +static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v); + +static int stk600_set_sck_period(PROGRAMMER * pgm, double v); + +static void stk600_setup_xprog(PROGRAMMER * pgm); +static void stk600_setup_isp(PROGRAMMER * pgm); +static int stk600_xprog_program_enable(PROGRAMMER * pgm, AVRPART * p); + +void stk500v2_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: stk500v2_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); + PDATA(pgm)->command_sequence = 1; +} + +static void stk500v2_jtagmkII_setup(PROGRAMMER * pgm) +{ + void *mycookie, *theircookie; + + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: stk500v2_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); + PDATA(pgm)->command_sequence = 1; + + /* + * Now, have the JTAG ICE mkII backend allocate its own private + * data. Store our own cookie in a safe place for the time being. + */ + mycookie = pgm->cookie; + jtagmkII_setup(pgm); + theircookie = pgm->cookie; + pgm->cookie = mycookie; + PDATA(pgm)->chained_pdata = theircookie; +} + +void stk500v2_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + +static void stk500v2_jtagmkII_teardown(PROGRAMMER * pgm) +{ + void *mycookie; + + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + jtagmkII_teardown(pgm); + + free(mycookie); +} + + +static unsigned short +b2_to_u16(unsigned char *b) +{ + unsigned short l; + l = b[0]; + l += (unsigned)b[1] << 8; + + return l; +} + +static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + if (serial_send(&pgm->fd, data, len) != 0) { + fprintf(stderr,"%s: stk500_send_mk2(): failed to send command to serial port\n",progname); + exit(1); + } + + return 0; +} + +static unsigned short get_jtagisp_return_size(unsigned char cmd) +{ + int i; + + for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++) + if (jtagispcmds[i].cmd == cmd) + return jtagispcmds[i].size; + + return 0; +} + +/* + * Send the data as a JTAG ICE mkII encapsulated ISP packet. + * Unlike what AVR067 says, the packet gets a length of our + * response buffer prepended, and replies with RSP_SPI_DATA + * if successful. + */ +static int stk500v2_jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + unsigned char *cmdbuf; + int rv; + unsigned short sz; + void *mycookie; + + sz = get_jtagisp_return_size(data[0]); + if (sz == 0) { + fprintf(stderr, "%s: unsupported encapsulated ISP command: %#x\n", + progname, data[0]); + return -1; + } + if (sz == SZ_READ_FLASH_EE) { + /* + * For CMND_READ_FLASH_ISP and CMND_READ_EEPROM_ISP, extract the + * size of the return data from the request. Note that the + * request itself has the size in big endian format, while we are + * supposed to deliver it in little endian. + */ + sz = 3 + (data[1] << 8) + data[2]; + } else if (sz == SZ_SPI_MULTI) { + /* + * CMND_SPI_MULTI has the Rx size encoded in its 3rd byte. + */ + sz = 3 + data[2]; + } + + if ((cmdbuf = malloc(len + 3)) == NULL) { + fprintf(stderr, "%s: out of memory for command packet\n", + progname); + exit(1); + } + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + cmdbuf[0] = CMND_ISP_PACKET; + cmdbuf[1] = sz & 0xff; + cmdbuf[2] = (sz >> 8) & 0xff; + memcpy(cmdbuf + 3, data, len); + rv = jtagmkII_send(pgm, cmdbuf, len + 3); + free(cmdbuf); + pgm->cookie = mycookie; + + return rv; +} + +static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + unsigned char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead + int i; + + if (PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || + PDATA(pgm)->pgmtype == PGMTYPE_STK600) + return stk500v2_send_mk2(pgm, data, len); + else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) + return stk500v2_jtagmkII_send(pgm, data, len); + + buf[0] = MESSAGE_START; + buf[1] = PDATA(pgm)->command_sequence; + buf[2] = len / 256; + buf[3] = len % 256; + buf[4] = TOKEN; + memcpy(buf+5, data, len); + + // calculate the XOR checksum + buf[5+len] = 0; + for (i=0;i<5+len;i++) + buf[5+len] ^= buf[i]; + + DEBUG("STK500V2: stk500v2_send("); + for (i=0;ifd, buf, len+6) != 0) { + fprintf(stderr,"%s: stk500_send(): failed to send command to serial port\n",progname); + exit(1); + } + + return 0; +} + + +int stk500v2_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(&pgm->fd, display); +} + +static int stk500v2_recv_mk2(PROGRAMMER * pgm, unsigned char msg[], + size_t maxsize) +{ + int rv; + + rv = serial_recv(&pgm->fd, msg, maxsize); + if (rv < 0) { + fprintf(stderr, "%s: stk500v2_recv_mk2: error in USB receive\n", progname); + return -1; + } + + return rv; +} + +static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char msg[], + size_t maxsize) +{ + int rv; + unsigned char *jtagmsg; + void *mycookie; + + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + rv = jtagmkII_recv(pgm, &jtagmsg); + pgm->cookie = mycookie; + if (rv <= 0) { + fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): error in jtagmkII_recv()\n", + progname); + return -1; + } + if (rv - 1 > maxsize) { + fprintf(stderr, + "%s: stk500v2_jtagmkII_recv(): got %u bytes, have only room for %u bytes\n", + progname, (unsigned)rv - 1, (unsigned)maxsize); + rv = maxsize; + } + switch (jtagmsg[0]) { + case RSP_SPI_DATA: + break; + case RSP_FAILED: + fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): failed\n", + progname); + return -1; + case RSP_ILLEGAL_MCU_STATE: + fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): illegal MCU state\n", + progname); + return -1; + default: + fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): unknown status %d\n", + progname, jtagmsg[0]); + return -1; + } + memcpy(msg, jtagmsg + 1, rv - 1); + return rv; +} + +static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) { + enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE } state = sSTART; + unsigned int msglen = 0; + unsigned int curlen = 0; + int timeout = 0; + unsigned char c, checksum = 0; + + long timeoutval = SERIAL_TIMEOUT; // seconds + struct timeval tv; + double tstart, tnow; + + if (PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || + PDATA(pgm)->pgmtype == PGMTYPE_STK600) + return stk500v2_recv_mk2(pgm, msg, maxsize); + else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) + return stk500v2_jtagmkII_recv(pgm, msg, maxsize); + + DEBUG("STK500V2: stk500v2_recv(): "); + + gettimeofday(&tv, NULL); + tstart = tv.tv_sec; + + while ( (state != sDONE ) && (!timeout) ) { + if (serial_recv(&pgm->fd, &c, 1) < 0) + goto timedout; + DEBUG("0x%02x ",c); + checksum ^= c; + + switch (state) { + case sSTART: + DEBUGRECV("hoping for start token..."); + if (c == MESSAGE_START) { + DEBUGRECV("got it\n"); + checksum = MESSAGE_START; + state = sSEQNUM; + } else + DEBUGRECV("sorry\n"); + break; + case sSEQNUM: + DEBUGRECV("hoping for sequence...\n"); + if (c == PDATA(pgm)->command_sequence) { + DEBUGRECV("got it, incrementing\n"); + state = sSIZE1; + PDATA(pgm)->command_sequence++; + } else { + DEBUGRECV("sorry\n"); + state = sSTART; + } + break; + case sSIZE1: + DEBUGRECV("hoping for size LSB\n"); + msglen = (unsigned)c * 256; + state = sSIZE2; + break; + case sSIZE2: + DEBUGRECV("hoping for size MSB..."); + msglen += (unsigned)c; + DEBUG(" msg is %u bytes\n",msglen); + state = sTOKEN; + break; + case sTOKEN: + if (c == TOKEN) state = sDATA; + else state = sSTART; + break; + case sDATA: + if (curlen < maxsize) { + msg[curlen] = c; + } else { + fprintf(stderr, "%s: stk500v2_recv(): buffer too small, received %d byte into %u byte buffer\n", + progname,curlen,(unsigned int)maxsize); + return -2; + } + if ((curlen == 0) && (msg[0] == ANSWER_CKSUM_ERROR)) { + fprintf(stderr, "%s: stk500v2_recv(): previous packet sent with wrong checksum\n", + progname); + return -3; + } + curlen++; + if (curlen == msglen) state = sCSUM; + break; + case sCSUM: + if (checksum == 0) { + state = sDONE; + } else { + state = sSTART; + fprintf(stderr, "%s: stk500v2_recv(): checksum error\n", + progname); + return -4; + } + break; + default: + fprintf(stderr, "%s: stk500v2_recv(): unknown state\n", + progname); + return -5; + } /* switch */ + + gettimeofday(&tv, NULL); + tnow = tv.tv_sec; + if (tnow-tstart > timeoutval) { // wuff - signed/unsigned/overflow + timedout: + fprintf(stderr, "%s: stk500v2_ReceiveMessage(): timeout\n", + progname); + return -1; + } + + } /* while */ + DEBUG("\n"); + + return (int)(msglen+6); +} + + + +int stk500v2_getsync(PROGRAMMER * pgm) { + int tries = 0; + unsigned char buf[1], resp[32]; + int status; + + DEBUG("STK500V2: stk500v2_getsync()\n"); + + if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) + return 0; + +retry: + tries++; + + // send the sync command and see if we can get there + buf[0] = CMD_SIGN_ON; + stk500v2_send(pgm, buf, 1); + + // try to get the response back and see where we got + status = stk500v2_recv(pgm, resp, sizeof(resp)); + + // if we got bytes returned, check to see what came back + if (status > 0) { + if ((resp[0] == CMD_SIGN_ON) && (resp[1] == STATUS_CMD_OK) && + (status > 3)) { + // success! + unsigned int siglen = resp[2]; + if (siglen >= strlen("STK500_2") && + memcmp(resp + 3, "STK500_2", strlen("STK500_2")) == 0) { + PDATA(pgm)->pgmtype = PGMTYPE_STK500; + } else if (siglen >= strlen("AVRISP_2") && + memcmp(resp + 3, "AVRISP_2", strlen("AVRISP_2")) == 0) { + PDATA(pgm)->pgmtype = PGMTYPE_AVRISP; + } else if (siglen >= strlen("AVRISP_MK2") && + memcmp(resp + 3, "AVRISP_MK2", strlen("AVRISP_MK2")) == 0) { + PDATA(pgm)->pgmtype = PGMTYPE_AVRISP_MKII; + } else if (siglen >= strlen("STK600") && + memcmp(resp + 3, "STK600", strlen("STK600")) == 0) { + PDATA(pgm)->pgmtype = PGMTYPE_STK600; + } else { + resp[siglen + 3] = 0; + if (verbose) + fprintf(stderr, + "%s: stk500v2_getsync(): got response from unknown " + "programmer %s, assuming STK500\n", + progname, resp + 3); + PDATA(pgm)->pgmtype = PGMTYPE_STK500; + } + if (verbose >= 3) + fprintf(stderr, + "%s: stk500v2_getsync(): found %s programmer\n", + progname, pgmname[PDATA(pgm)->pgmtype]); + return 0; + } else { + if (tries > RETRIES) { + fprintf(stderr, + "%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n", + progname, resp[0]); + return -6; + } else + goto retry; + } + + // or if we got a timeout + } else if (status == -1) { + if (tries > RETRIES) { + fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n", + progname); + return -1; + } else + goto retry; + + // or any other error + } else { + if (tries > RETRIES) { + fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n", + progname,status); + } else + goto retry; + } + + return 0; +} + +static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf, + size_t len, size_t maxlen) { + int i; + int tries = 0; + int status; + + DEBUG("STK500V2: stk500v2_command("); + for (i=0;i 0) { + DEBUG(" = %d\n",status); + if (status < 2) { + fprintf(stderr, "%s: stk500v2_command(): short reply\n", progname); + return -1; + } + if (buf[0] == CMD_XPROG_SETMODE || buf[0] == CMD_XPROG) { + /* + * Decode XPROG wrapper errors. + */ + const char *msg; + int i; + + /* + * For CMD_XPROG_SETMODE, the status is returned in buf[1]. + * For CMD_XPROG, buf[1] contains the XPRG_CMD_* command, and + * buf[2] contains the status. + */ + i = buf[0] == CMD_XPROG_SETMODE? 1: 2; + + if (buf[i] != XPRG_ERR_OK) { + switch (buf[i]) { + case XPRG_ERR_FAILED: msg = "Failed"; break; + case XPRG_ERR_COLLISION: msg = "Collision"; break; + case XPRG_ERR_TIMEOUT: msg = "Timeout"; break; + default: msg = "Unknown"; break; + } + fprintf(stderr, "%s: stk500v2_command(): error in %s: %s\n", + progname, + (buf[0] == CMD_XPROG_SETMODE? "CMD_XPROG_SETMODE": "CMD_XPROG"), + msg); + return -1; + } + return 0; + } else { + /* + * Decode STK500v2 errors. + */ + if (buf[1] >= STATUS_CMD_TOUT && buf[1] < 0xa0) { + const char *msg; + char msgbuf[30]; + switch (buf[1]) { + case STATUS_CMD_TOUT: + msg = "Command timed out"; + break; + + case STATUS_RDY_BSY_TOUT: + msg = "Sampling of the RDY/nBSY pin timed out"; + break; + + case STATUS_SET_PARAM_MISSING: + msg = "The `Set Device Parameters' have not been " + "executed in advance of this command"; + + default: + sprintf(msgbuf, "unknown, code 0x%02x", buf[1]); + msg = msgbuf; + break; + } + if (quell_progress < 2) + fprintf(stderr, "%s: stk500v2_command(): warning: %s\n", + progname, msg); + buf[1] = STATUS_CMD_OK; /* pretend success */ + } + if (buf[1] == STATUS_CMD_OK) + return status; + if (buf[1] == STATUS_CMD_FAILED) + fprintf(stderr, "%s: stk500v2_command(): command failed\n", progname); + else + fprintf(stderr, "%s: stk500v2_command(): unknown status 0x%02x\n", + progname, buf[1]); + return -1; + } + } + + // otherwise try to sync up again + status = stk500v2_getsync(pgm); + if (status != 0) { + if (tries > RETRIES) { + fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n", + progname,buf[0]); + return -1; + } else + goto retry; + } + + DEBUG(" = 0\n"); + return 0; +} + +static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + unsigned char buf[8]; + int result; + + DEBUG("STK500V2: stk500v2_cmd(%02x,%02x,%02x,%02x)\n",cmd[0],cmd[1],cmd[2],cmd[3]); + + buf[0] = CMD_SPI_MULTI; + buf[1] = 4; + buf[2] = 4; + buf[3] = 0; + buf[4] = cmd[0]; + buf[5] = cmd[1]; + buf[6] = cmd[2]; + buf[7] = cmd[3]; + + result = stk500v2_command(pgm, buf, 8, sizeof(buf)); + if (result < 0) { + fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n", + progname); + return -1; + } else if (result < 6) { + fprintf(stderr, "%s: stk500v2_cmd(): short reply, len = %d\n", + progname, result); + return -1; + } + + res[0] = buf[2]; + res[1] = buf[3]; + res[2] = buf[4]; + res[3] = buf[5]; + + return 0; +} + + +/* + * issue the 'chip erase' command to the AVR device + */ +static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + int result; + unsigned char buf[16]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "%s: stk500v2_chip_erase: chip erase instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + buf[0] = CMD_CHIP_ERASE_ISP; + buf[1] = p->chip_erase_delay / 1000; + buf[2] = 0; // use delay (?) + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], buf+3); + result = stk500v2_command(pgm, buf, 7, sizeof(buf)); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return result >= 0? 0: -1; +} + +/* + * issue the 'chip erase' command to the AVR device, generic HV mode + */ +static int stk500hv_chip_erase(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode) +{ + int result; + unsigned char buf[3]; + + pgm->pgm_led(pgm, ON); + + if (mode == PPMODE) { + buf[0] = CMD_CHIP_ERASE_PP; + buf[1] = p->chiperasepulsewidth; + buf[2] = p->chiperasepolltimeout; + } else { + buf[0] = CMD_CHIP_ERASE_HVSP; + buf[1] = p->chiperasepolltimeout; + buf[2] = p->chiperasetime; + } + result = stk500v2_command(pgm, buf, 3, sizeof(buf)); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return result >= 0? 0: -1; +} + +/* + * issue the 'chip erase' command to the AVR device, parallel mode + */ +static int stk500pp_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + return stk500hv_chip_erase(pgm, p, PPMODE); +} + +/* + * issue the 'chip erase' command to the AVR device, HVSP mode + */ +static int stk500hvsp_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + return stk500hv_chip_erase(pgm, p, HVSPMODE); +} + +static struct +{ + unsigned int state; + const char *description; +} connection_status[] = +{ + { STATUS_CONN_FAIL_MOSI, "MOSI fail" }, + { STATUS_CONN_FAIL_RST, "RST fail" }, + { STATUS_CONN_FAIL_SCK, "SCK fail" }, + { STATUS_TGT_NOT_DETECTED, "Target not detected" }, + { STATUS_TGT_REVERSE_INSERTED, "Target reverse inserted" }, +}; + +/* + * Max length of returned message is the sum of all the description + * strings in the table above, plus 2 characters for separation. + * Currently, this is 76 chars. + */ +static void +stk500v2_translate_conn_status(unsigned char status, char *msg) +{ + size_t i; + int need_comma; + + *msg = 0; + need_comma = 0; + + for (i = 0; + i < sizeof connection_status / sizeof connection_status[0]; + i++) + { + if ((status & connection_status[i].state) != 0) + { + if (need_comma) + strcat(msg, ", "); + strcat(msg, connection_status[i].description); + need_comma = 1; + } + } + if (*msg == 0) + sprintf(msg, "Unknown status 0x%02x", status); +} + + +/* + * issue the 'program enable' command to the AVR device + */ +static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[16]; + char msg[100]; /* see remarks above about size needed */ + int rv; + + PDATA(pgm)->lastpart = p; + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) { + fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + + if (PDATA(pgm)->pgmtype == PGMTYPE_STK500 || + PDATA(pgm)->pgmtype == PGMTYPE_STK600) + /* Activate AVR-style (low active) RESET */ + stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01); + + buf[0] = CMD_ENTER_PROGMODE_ISP; + buf[1] = p->timeout; + buf[2] = p->stabdelay; + buf[3] = p->cmdexedelay; + buf[4] = p->synchloops; + buf[5] = p->bytedelay; + buf[6] = p->pollvalue; + buf[7] = p->pollindex; + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf+8); + buf[10] = buf[11] = 0; + + rv = stk500v2_command(pgm, buf, 12, sizeof(buf)); + + if (rv < 0) { + switch (PDATA(pgm)->pgmtype) + { + case PGMTYPE_STK600: + case PGMTYPE_AVRISP_MKII: + if (stk500v2_getparm(pgm, PARAM_STATUS_TGT_CONN, &buf[0]) != 0) { + fprintf(stderr, + "%s: stk500v2_program_enable(): cannot get connection status\n", + progname); + } else { + stk500v2_translate_conn_status(buf[0], msg); + fprintf(stderr, "%s: stk500v2_program_enable():" + " bad AVRISPmkII connection status: %s\n", + progname, msg); + } + break; + + default: + /* cannot report anything for other pgmtypes */ + break; + } + } + + return rv; +} + +/* + * issue the 'program enable' command to the AVR device, parallel mode + */ +static int stk500pp_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[16]; + + PDATA(pgm)->lastpart = p; + + buf[0] = CMD_ENTER_PROGMODE_PP; + buf[1] = p->hventerstabdelay; + buf[2] = p->progmodedelay; + buf[3] = p->latchcycles; + buf[4] = p->togglevtg; + buf[5] = p->poweroffdelay; + buf[6] = p->resetdelayms; + buf[7] = p->resetdelayus; + + return stk500v2_command(pgm, buf, 8, sizeof(buf)); +} + +/* + * issue the 'program enable' command to the AVR device, HVSP mode + */ +static int stk500hvsp_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[16]; + + PDATA(pgm)->lastpart = p; + + buf[0] = PDATA(pgm)->pgmtype == PGMTYPE_STK600? + CMD_ENTER_PROGMODE_HVSP_STK600: + CMD_ENTER_PROGMODE_HVSP; + buf[1] = p->hventerstabdelay; + buf[2] = p->hvspcmdexedelay; + buf[3] = p->synchcycles; + buf[4] = p->latchcycles; + buf[5] = p->togglevtg; + buf[6] = p->poweroffdelay; + buf[7] = p->resetdelayms; + buf[8] = p->resetdelayus; + + return stk500v2_command(pgm, buf, 9, sizeof(buf)); +} + + + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + + if ((PDATA(pgm)->pgmtype == PGMTYPE_STK600 || + PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || + PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) != 0 + && (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) != 0) { + /* + * This is an ATxmega device, must use XPROG protocol for the + * remaining actions. + */ + stk600_setup_xprog(pgm); + } else { + stk600_setup_isp(pgm); + } + + return pgm->program_enable(pgm, p); +} + + +/* + * initialize the AVR device and prepare it to accept commands, generic HV mode + */ +static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode) +{ + unsigned char buf[CTL_STACK_SIZE + 1]; + int result; + LNODEID ln; + AVRMEM * m; + + if (p->ctl_stack_type != (mode == PPMODE? CTL_STACK_PP: CTL_STACK_HVSP)) { + fprintf(stderr, + "%s: stk500hv_initialize(): " + "%s programming control stack not defined for part \"%s\"\n", + progname, + (mode == PPMODE? "parallel": "high-voltage serial"), + p->desc); + return -1; + } + + buf[0] = CMD_SET_CONTROL_STACK; + memcpy(buf + 1, p->controlstack, CTL_STACK_SIZE); + + result = stk500v2_command(pgm, buf, CTL_STACK_SIZE + 1, sizeof(buf)); + + if (result < 0) { + fprintf(stderr, + "%s: stk500pp_initalize(): " + "failed to set control stack\n", + progname); + return -1; + } + + /* + * Examine the avrpart's memory definitions, and initialize the page + * caches. For devices/memory that are not page oriented, treat + * them as page size 1 for EEPROM, and 2 for flash. + */ + PDATA(pgm)->flash_pagesize = 2; + PDATA(pgm)->eeprom_pagesize = 1; + for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { + m = ldata(ln); + if (strcmp(m->desc, "flash") == 0) { + if (m->page_size > 0) + PDATA(pgm)->flash_pagesize = m->page_size; + } else if (strcmp(m->desc, "eeprom") == 0) { + if (m->page_size > 0) + PDATA(pgm)->eeprom_pagesize = m->page_size; + } + } + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { + fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n", + progname); + return -1; + } + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { + fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n", + progname); + free(PDATA(pgm)->flash_pagecache); + return -1; + } + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + + return pgm->program_enable(pgm, p); +} + +/* + * initialize the AVR device and prepare it to accept commands, PP mode + */ +static int stk500pp_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + return stk500hv_initialize(pgm, p, PPMODE); +} + +/* + * initialize the AVR device and prepare it to accept commands, HVSP mode + */ +static int stk500hvsp_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + return stk500hv_initialize(pgm, p, HVSPMODE); +} + +static void stk500v2_disable(PROGRAMMER * pgm) +{ + unsigned char buf[16]; + int result; + + buf[0] = CMD_LEAVE_PROGMODE_ISP; + buf[1] = 1; // preDelay; + buf[2] = 1; // postDelay; + + result = stk500v2_command(pgm, buf, 3, sizeof(buf)); + + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_disable(): failed to leave programming mode\n", + progname); + } + + return; +} + +/* + * Leave programming mode, generic HV mode + */ +static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode) +{ + unsigned char buf[16]; + int result; + + free(PDATA(pgm)->flash_pagecache); + PDATA(pgm)->flash_pagecache = NULL; + free(PDATA(pgm)->eeprom_pagecache); + PDATA(pgm)->eeprom_pagecache = NULL; + + buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP: + (PDATA(pgm)->pgmtype == PGMTYPE_STK600? + CMD_LEAVE_PROGMODE_HVSP_STK600: + CMD_LEAVE_PROGMODE_HVSP); + buf[1] = 15; // p->hvleavestabdelay; + buf[2] = 15; // p->resetdelay; + + result = stk500v2_command(pgm, buf, 3, sizeof(buf)); + + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_disable(): " + "failed to leave programming mode\n", + progname); + exit(1); + } + + return; +} + +/* + * Leave programming mode, PP mode + */ +static void stk500pp_disable(PROGRAMMER * pgm) +{ + stk500hv_disable(pgm, PPMODE); +} + +/* + * Leave programming mode, HVSP mode + */ +static void stk500hvsp_disable(PROGRAMMER * pgm) +{ + stk500hv_disable(pgm, HVSPMODE); +} + +static void stk500v2_enable(PROGRAMMER * pgm) +{ + return; +} + + +static int stk500v2_open(PROGRAMMER * pgm, char * port) +{ + long baud = 115200; + + DEBUG("STK500V2: stk500v2_open()\n"); + + if (pgm->baudrate) + baud = pgm->baudrate; + + PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN; + + if(strcasecmp(port, "avrdoper") == 0){ +#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) + serdev = &avrdoper_serdev; + PDATA(pgm)->pgmtype = PGMTYPE_STK500; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev_frame; + baud = USB_DEVICE_AVRISPMKII; + PDATA(pgm)->pgmtype = PGMTYPE_AVRISP_MKII; + pgm->set_sck_period = stk500v2_set_sck_period_mk2; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + stk500v2_drain(pgm, 0); + + stk500v2_getsync(pgm); + + stk500v2_drain(pgm, 0); + + if (pgm->bitclock != 0.0) { + if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + return 0; +} + + +static int stk600_open(PROGRAMMER * pgm, char * port) +{ + long baud = 115200; + + DEBUG("STK500V2: stk600_open()\n"); + + if (pgm->baudrate) + baud = pgm->baudrate; + + PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev_frame; + baud = USB_DEVICE_STK600; + PDATA(pgm)->pgmtype = PGMTYPE_STK600; + pgm->set_sck_period = stk600_set_sck_period; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + stk500v2_drain(pgm, 0); + + stk500v2_getsync(pgm); + + stk500v2_drain(pgm, 0); + + if (pgm->bitclock != 0.0) { + if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + return 0; +} + + +static void stk500v2_close(PROGRAMMER * pgm) +{ + DEBUG("STK500V2: stk500v2_close()\n"); + + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + + +static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr) +{ + unsigned char buf[16]; + int result; + + DEBUG("STK500V2: stk500v2_loadaddr(%d)\n",addr); + + buf[0] = CMD_LOAD_ADDRESS; + buf[1] = (addr >> 24) & 0xff; + buf[2] = (addr >> 16) & 0xff; + buf[3] = (addr >> 8) & 0xff; + buf[4] = addr & 0xff; + + result = stk500v2_command(pgm, buf, 5, sizeof(buf)); + + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_loadaddr(): failed to set load address\n", + progname); + return -1; + } + + return 0; +} + + +/* + * Read a single byte, generic HV mode + */ +static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value, + enum hvmode mode) +{ + int result, cmdlen = 2; + unsigned char buf[266]; + unsigned long paddr = 0UL, *paddr_ptr = NULL; + unsigned int pagesize = 0, use_ext_addr = 0, addrshift = 0; + unsigned char *cache_ptr = NULL; + + if (verbose >= 2) + fprintf(stderr, "%s: stk500hv_read_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + if (strcmp(mem->desc, "flash") == 0) { + buf[0] = mode == PPMODE? CMD_READ_FLASH_PP: CMD_READ_FLASH_HVSP; + cmdlen = 3; + pagesize = mem->page_size; + if (pagesize == 0) + pagesize = 2; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; + addrshift = 1; + /* + * If bit 31 is set, this indicates that the following read/write + * operation will be performed on a memory that is larger than + * 64KBytes. This is an indication to STK500 that a load extended + * address must be executed. + */ + if (mem->op[AVR_OP_LOAD_EXT_ADDR] != NULL) { + use_ext_addr = (1U << 31); + } + } else if (strcmp(mem->desc, "eeprom") == 0) { + buf[0] = mode == PPMODE? CMD_READ_EEPROM_PP: CMD_READ_EEPROM_HVSP; + cmdlen = 3; + pagesize = mem->page_size; + if (pagesize == 0) + pagesize = 1; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; + } else if (strcmp(mem->desc, "lfuse") == 0 || + strcmp(mem->desc, "fuse") == 0) { + buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP; + addr = 0; + } else if (strcmp(mem->desc, "hfuse") == 0) { + buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP; + addr = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP; + addr = 2; + } else if (strcmp(mem->desc, "lock") == 0) { + buf[0] = mode == PPMODE? CMD_READ_LOCK_PP: CMD_READ_LOCK_HVSP; + } else if (strcmp(mem->desc, "calibration") == 0) { + buf[0] = mode == PPMODE? CMD_READ_OSCCAL_PP: CMD_READ_OSCCAL_HVSP; + } else if (strcmp(mem->desc, "signature") == 0) { + buf[0] = mode == PPMODE? CMD_READ_SIGNATURE_PP: CMD_READ_SIGNATURE_HVSP; + } + + /* + * In HV mode, we have to use paged reads for flash and + * EEPROM, and cache the results in a page cache. + * + * Page cache validation is based on "{flash,eeprom}_pageaddr" + * (holding the base address of the most recent cache fill + * operation). This variable is set to (unsigned long)-1L when the + * cache needs to be invalidated. + */ + if (pagesize && paddr == *paddr_ptr) { + *value = cache_ptr[addr & (pagesize - 1)]; + return 0; + } + + if (cmdlen == 3) { + /* long command, fill in # of bytes */ + buf[1] = (pagesize >> 8) & 0xff; + buf[2] = pagesize & 0xff; + + /* flash and EEPROM reads require the load address command */ + if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0) + return -1; + } else { + buf[1] = addr; + } + + if (verbose >= 2) + fprintf(stderr, "%s: stk500hv_read_byte(): Sending read memory command: ", + progname); + + result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf)); + + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_read_byte(): " + "timeout/error communicating with programmer\n", + progname); + return -1; + } + + if (pagesize) { + *paddr_ptr = paddr; + memcpy(cache_ptr, buf + 2, pagesize); + *value = cache_ptr[addr & (pagesize - 1)]; + } else { + *value = buf[2]; + } + + return 0; +} + +/* + * Read a single byte, PP mode + */ +static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + return stk500hv_read_byte(pgm, p, mem, addr, value, PPMODE); +} + +/* + * Read a single byte, HVSP mode + */ +static int stk500hvsp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + return stk500hv_read_byte(pgm, p, mem, addr, value, HVSPMODE); +} + +/* + * Write one byte, generic HV mode + */ +static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data, + enum hvmode mode) +{ + int result, cmdlen, timeout = 0, pulsewidth = 0; + unsigned char buf[266]; + unsigned long paddr = 0UL, *paddr_ptr = NULL; + unsigned int pagesize = 0, use_ext_addr = 0, addrshift = 0; + unsigned char *cache_ptr = NULL; + + if (verbose >= 2) + fprintf(stderr, "%s: stk500hv_write_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + if (strcmp(mem->desc, "flash") == 0) { + buf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP; + pagesize = mem->page_size; + if (pagesize == 0) + pagesize = 2; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; + addrshift = 1; + /* + * If bit 31 is set, this indicates that the following read/write + * operation will be performed on a memory that is larger than + * 64KBytes. This is an indication to STK500 that a load extended + * address must be executed. + */ + if (mem->op[AVR_OP_LOAD_EXT_ADDR] != NULL) { + use_ext_addr = (1U << 31); + } + } else if (strcmp(mem->desc, "eeprom") == 0) { + buf[0] = mode == PPMODE? CMD_PROGRAM_EEPROM_PP: CMD_PROGRAM_EEPROM_HVSP; + pagesize = mem->page_size; + if (pagesize == 0) + pagesize = 1; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; + } else if (strcmp(mem->desc, "lfuse") == 0 || + strcmp(mem->desc, "fuse") == 0) { + buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP; + addr = 0; + pulsewidth = p->programfusepulsewidth; + timeout = p->programfusepolltimeout; + } else if (strcmp(mem->desc, "hfuse") == 0) { + buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP; + addr = 1; + pulsewidth = p->programfusepulsewidth; + timeout = p->programfusepolltimeout; + } else if (strcmp(mem->desc, "efuse") == 0) { + buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP; + addr = 2; + pulsewidth = p->programfusepulsewidth; + timeout = p->programfusepolltimeout; + } else if (strcmp(mem->desc, "lock") == 0) { + buf[0] = mode == PPMODE? CMD_PROGRAM_LOCK_PP: CMD_PROGRAM_LOCK_HVSP; + pulsewidth = p->programlockpulsewidth; + timeout = p->programlockpolltimeout; + } else { + fprintf(stderr, + "%s: stk500hv_write_byte(): " + "unsupported memory type: %s\n", + progname, mem->desc); + return -1; + } + + cmdlen = 5 + pagesize; + + /* + * In HV mode, we have to use paged writes for flash and + * EEPROM. As both, flash and EEPROM cells can only be programmed + * from `1' to `0' bits (even EEPROM does not support auto-erase in + * parallel mode), we just pre-fill the page cache with 0xff, so all + * those cells that are outside our current address will remain + * unaffected. + */ + if (pagesize) { + memset(cache_ptr, 0xff, pagesize); + cache_ptr[addr & (pagesize - 1)] = data; + + /* long command, fill in # of bytes */ + buf[1] = (pagesize >> 8) & 0xff; + buf[2] = pagesize & 0xff; + + /* + * Synthesize the mode byte. This is simpler than adding yet + * another parameter to the avrdude.conf file. We calculate the + * bits corresponding to the page size, as explained in AVR068. + * We set bit 7, to indicate this is to actually write the page to + * the target device. We set bit 6 to indicate this is the very + * last page to be programmed, whatever this means -- we just + * pretend we don't know any better. ;-) Bit 0 is set if this is + * a paged memory, which means it has a page size of more than 2. + */ + buf[3] = 0x80 | 0x40; + if (pagesize > 2) { + buf[3] |= stk500v2_mode_for_pagesize(pagesize); + buf[3] |= 0x01; + } + buf[4] = mem->delay; + memcpy(buf + 5, cache_ptr, pagesize); + + /* flash and EEPROM reads require the load address command */ + if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0) + return -1; + } else { + buf[1] = addr; + buf[2] = data; + if (mode == PPMODE) { + buf[3] = pulsewidth; + buf[4] = timeout; + } else { + buf[3] = timeout; + cmdlen--; + } + } + + if (verbose >= 2) + fprintf(stderr, "%s: stk500hv_write_byte(): Sending write memory command: ", + progname); + + result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf)); + + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_write_byte(): " + "timeout/error communicating with programmer\n", + progname); + return -1; + } + + if (pagesize) { + /* Invalidate the page cache. */ + *paddr_ptr = (unsigned long)-1L; + } + + return 0; +} + +/* + * Write one byte, PP mode + */ +static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + return stk500hv_write_byte(pgm, p, mem, addr, data, PPMODE); +} + +/* + * Write one byte, HVSP mode + */ +static int stk500hvsp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + return stk500hv_write_byte(pgm, p, mem, addr, data, HVSPMODE); +} + + +static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned int addr, block_size, last_addr, hiaddr, addrshift, use_ext_addr; + unsigned char commandbuf[10]; + unsigned char buf[266]; + unsigned char cmds[4]; + int result; + OPCODE * rop, * wop; + + DEBUG("STK500V2: stk500v2_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes); + + if (page_size == 0) page_size = 256; + hiaddr = UINT_MAX; + addrshift = 0; + use_ext_addr = 0; + + // determine which command is to be used + if (strcmp(m->desc, "flash") == 0) { + addrshift = 1; + commandbuf[0] = CMD_PROGRAM_FLASH_ISP; + /* + * If bit 31 is set, this indicates that the following read/write + * operation will be performed on a memory that is larger than + * 64KBytes. This is an indication to STK500 that a load extended + * address must be executed. + */ + if (m->op[AVR_OP_LOAD_EXT_ADDR] != NULL) { + use_ext_addr = (1U << 31); + } + } else if (strcmp(m->desc, "eeprom") == 0) { + commandbuf[0] = CMD_PROGRAM_EEPROM_ISP; + } + commandbuf[4] = m->delay; + + if (addrshift == 0) { + wop = m->op[AVR_OP_WRITE]; + rop = m->op[AVR_OP_READ]; + } + else { + wop = m->op[AVR_OP_WRITE_LO]; + rop = m->op[AVR_OP_READ_LO]; + } + + // if the memory is paged, load the appropriate commands into the buffer + if (m->mode & 0x01) { + commandbuf[3] = m->mode | 0x80; // yes, write the page to flash + + if (m->op[AVR_OP_LOADPAGE_LO] == NULL) { + fprintf(stderr, "%s: stk500v2_paged_write: loadpage instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], cmds); + commandbuf[5] = cmds[0]; + + if (m->op[AVR_OP_WRITEPAGE] == NULL) { + fprintf(stderr, "%s: stk500v2_paged_write: write page instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + avr_set_bits(m->op[AVR_OP_WRITEPAGE], cmds); + commandbuf[6] = cmds[0]; + + // otherwise, we need to load different commands in + } + else { + commandbuf[3] = m->mode | 0x80; // yes, write the words to flash + + if (wop == NULL) { + fprintf(stderr, "%s: stk500v2_paged_write: write instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + avr_set_bits(wop, cmds); + commandbuf[5] = cmds[0]; + commandbuf[6] = 0; + } + + // the read command is common to both methods + if (rop == NULL) { + fprintf(stderr, "%s: stk500v2_paged_write: read instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + avr_set_bits(rop, cmds); + commandbuf[7] = cmds[0]; + + commandbuf[8] = m->readback[0]; + commandbuf[9] = m->readback[1]; + + last_addr=UINT_MAX; /* impossible address */ + + for (addr=0; addr < n_bytes; addr += page_size) { + report_progress(addr,n_bytes,NULL); + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + + DEBUG("block_size at addr %d is %d\n",addr,block_size); + + if(commandbuf[0] == CMD_PROGRAM_FLASH_ISP){ + if (stk500v2_is_page_empty(addr, block_size, m->buf)) { + continue; + } + } + + memcpy(buf,commandbuf,sizeof(commandbuf)); + + buf[1] = block_size >> 8; + buf[2] = block_size & 0xff; + + if((last_addr==UINT_MAX)||(last_addr+block_size != addr)){ + if (stk500v2_loadaddr(pgm, use_ext_addr | (addr >> addrshift)) < 0) + return -1; + } + last_addr=addr; + + memcpy(buf+10,m->buf+addr, block_size); + + result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf)); + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_paged_write: write command failed\n", + progname); + return -1; + } + } + + return n_bytes; +} + +/* + * Write pages of flash/EEPROM, generic HV mode + */ +static int stk500hv_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes, + enum hvmode mode) +{ + unsigned int addr, block_size, last_addr, hiaddr, addrshift, use_ext_addr; + unsigned char commandbuf[5], buf[266]; + int result; + + DEBUG("STK500V2: stk500hv_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes); + + hiaddr = UINT_MAX; + addrshift = 0; + use_ext_addr = 0; + + // determine which command is to be used + if (strcmp(m->desc, "flash") == 0) { + addrshift = 1; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + commandbuf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP; + /* + * If bit 31 is set, this indicates that the following read/write + * operation will be performed on a memory that is larger than + * 64KBytes. This is an indication to STK500 that a load extended + * address must be executed. + */ + if (m->op[AVR_OP_LOAD_EXT_ADDR] != NULL) { + use_ext_addr = (1U << 31); + } + } else if (strcmp(m->desc, "eeprom") == 0) { + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + commandbuf[0] = mode == PPMODE? CMD_PROGRAM_EEPROM_PP: CMD_PROGRAM_EEPROM_HVSP; + } + /* + * Synthesize the mode byte. This is simpler than adding yet + * another parameter to the avrdude.conf file. We calculate the + * bits corresponding to the page size, as explained in AVR068. We + * set bit 7, to indicate this is to actually write the page to the + * target device. We set bit 6 to indicate this is the very last + * page to be programmed, whatever this means -- we just pretend we + * don't know any better. ;-) Finally, we set bit 0 to say this is + * a paged memory, after all, that's why we got here at all. + */ + commandbuf[3] = 0x80 | 0x40; + if (page_size > 2) { + commandbuf[3] |= stk500v2_mode_for_pagesize(page_size); + commandbuf[3] |= 0x01; + } + commandbuf[4] = m->delay; + + if (page_size == 0) page_size = 256; + + last_addr = UINT_MAX; /* impossible address */ + + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr,n_bytes,NULL); + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + + DEBUG("block_size at addr %d is %d\n",addr,block_size); + + if (addrshift == 1) { + if (stk500v2_is_page_empty(addr, block_size, m->buf)) { + continue; + } + } + + memcpy(buf, commandbuf, sizeof(commandbuf)); + + buf[1] = page_size >> 8; + buf[2] = page_size & 0xff; + + if ((last_addr == UINT_MAX) || (last_addr + block_size != addr)) { + if (stk500v2_loadaddr(pgm, use_ext_addr | (addr >> addrshift)) < 0) + return -1; + } + last_addr=addr; + + memcpy(buf + 5, m->buf + addr, block_size); + if (block_size != page_size) + memset(buf + 5 + block_size, 0xff, page_size - block_size); + + result = stk500v2_command(pgm, buf, page_size + 5, sizeof(buf)); + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_paged_write: write command failed\n", + progname); + return -1; + } + } + + return n_bytes; +} + +/* + * Write pages of flash/EEPROM, PP mode + */ +static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + return stk500hv_paged_write(pgm, p, m, page_size, n_bytes, PPMODE); +} + +/* + * Write pages of flash/EEPROM, HVSP mode + */ +static int stk500hvsp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + return stk500hv_paged_write(pgm, p, m, page_size, n_bytes, HVSPMODE); +} + +static int stk500v2_is_page_empty(unsigned int address, int page_size, + const unsigned char *buf) +{ + int i; + for(i = 0; i < page_size; i++) { + if(buf[address + i] != 0xFF) { + /* Page is not empty. */ + return(0); + } + } + + /* Page is empty. */ + return(1); +} + +static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + unsigned int addr, block_size, hiaddr, addrshift, use_ext_addr; + unsigned char commandbuf[4]; + unsigned char buf[275]; // max buffer size for stk500v2 at this point + unsigned char cmds[4]; + int result; + OPCODE * rop; + + DEBUG("STK500V2: stk500v2_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes); + + page_size = m->readsize; + + rop = m->op[AVR_OP_READ]; + + hiaddr = UINT_MAX; + addrshift = 0; + use_ext_addr = 0; + + // determine which command is to be used + if (strcmp(m->desc, "flash") == 0) { + commandbuf[0] = CMD_READ_FLASH_ISP; + rop = m->op[AVR_OP_READ_LO]; + addrshift = 1; + /* + * If bit 31 is set, this indicates that the following read/write + * operation will be performed on a memory that is larger than + * 64KBytes. This is an indication to STK500 that a load extended + * address must be executed. + */ + if (m->op[AVR_OP_LOAD_EXT_ADDR] != NULL) { + use_ext_addr = (1U << 31); + } + } + else if (strcmp(m->desc, "eeprom") == 0) { + commandbuf[0] = CMD_READ_EEPROM_ISP; + } + + // the read command is common to both methods + if (rop == NULL) { + fprintf(stderr, "%s: stk500v2_paged_load: read instruction not defined for part \"%s\"\n", + progname, p->desc); + return -1; + } + avr_set_bits(rop, cmds); + commandbuf[3] = cmds[0]; + + for (addr=0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + DEBUG("block_size at addr %d is %d\n",addr,block_size); + + memcpy(buf,commandbuf,sizeof(commandbuf)); + + buf[1] = block_size >> 8; + buf[2] = block_size & 0xff; + + // Ensure a new "load extended address" will be issued + // when crossing a 64 KB boundary in flash. + if (hiaddr != (addr & ~0xFFFF)) { + hiaddr = addr & ~0xFFFF; + if (stk500v2_loadaddr(pgm, use_ext_addr | (addr >> addrshift)) < 0) + return -1; + } + + result = stk500v2_command(pgm,buf,4,sizeof(buf)); + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_paged_load: read command failed\n", + progname); + return -1; + } +#if 0 + for (i=0;ibuf[addr], &buf[2], block_size); + } + + return n_bytes; +} + + +/* + * Read pages of flash/EEPROM, generic HV mode + */ +static int stk500hv_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes, + enum hvmode mode) +{ + unsigned int addr, block_size, hiaddr, addrshift, use_ext_addr; + unsigned char commandbuf[3], buf[266]; + int result; + + DEBUG("STK500V2: stk500hv_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes); + + page_size = m->readsize; + + hiaddr = UINT_MAX; + addrshift = 0; + use_ext_addr = 0; + + // determine which command is to be used + if (strcmp(m->desc, "flash") == 0) { + commandbuf[0] = mode == PPMODE? CMD_READ_FLASH_PP: CMD_READ_FLASH_HVSP; + addrshift = 1; + /* + * If bit 31 is set, this indicates that the following read/write + * operation will be performed on a memory that is larger than + * 64KBytes. This is an indication to STK500 that a load extended + * address must be executed. + */ + if (m->op[AVR_OP_LOAD_EXT_ADDR] != NULL) { + use_ext_addr = (1U << 31); + } + } + else if (strcmp(m->desc, "eeprom") == 0) { + commandbuf[0] = mode == PPMODE? CMD_READ_EEPROM_PP: CMD_READ_EEPROM_HVSP; + } + + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes, NULL); + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + DEBUG("block_size at addr %d is %d\n",addr,block_size); + + memcpy(buf, commandbuf, sizeof(commandbuf)); + + buf[1] = block_size >> 8; + buf[2] = block_size & 0xff; + + // Ensure a new "load extended address" will be issued + // when crossing a 64 KB boundary in flash. + if (hiaddr != (addr & ~0xFFFF)) { + hiaddr = addr & ~0xFFFF; + if (stk500v2_loadaddr(pgm, use_ext_addr | (addr >> addrshift)) < 0) + return -1; + } + + result = stk500v2_command(pgm, buf, 3, sizeof(buf)); + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_paged_load: read command failed\n", + progname); + return -1; + } +#if 0 + for (i = 0; i < page_size; i++) { + fprintf(stderr, "%02X", buf[2 + i]); + if (i % 16 == 15) fprintf(stderr, "\n"); + } +#endif + + memcpy(&m->buf[addr], &buf[2], block_size); + } + + return n_bytes; +} + +/* + * Read pages of flash/EEPROM, PP mode + */ +static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + return stk500hv_paged_load(pgm, p, m, page_size, n_bytes, PPMODE); +} + +/* + * Read pages of flash/EEPROM, HVSP mode + */ +static int stk500hvsp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + return stk500hv_paged_load(pgm, p, m, page_size, n_bytes, HVSPMODE); +} + + +static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v) +{ + unsigned char uaref, utarg; + + utarg = (unsigned)((v + 0.049) * 10); + + if (stk500v2_getparm(pgm, PARAM_VADJUST, &uaref) != 0) { + fprintf(stderr, + "%s: stk500v2_set_vtarget(): cannot obtain V[aref]\n", + progname); + return -1; + } + + if (uaref > utarg) { + fprintf(stderr, + "%s: stk500v2_set_vtarget(): reducing V[aref] from %.1f to %.1f\n", + progname, uaref / 10.0, v); + if (stk500v2_setparm(pgm, PARAM_VADJUST, utarg) + != 0) + return -1; + } + return stk500v2_setparm(pgm, PARAM_VTARGET, utarg); +} + + +static int stk500v2_set_varef(PROGRAMMER * pgm, unsigned int chan /* unused */, + double v) +{ + unsigned char uaref, utarg; + + uaref = (unsigned)((v + 0.049) * 10); + + if (stk500v2_getparm(pgm, PARAM_VTARGET, &utarg) != 0) { + fprintf(stderr, + "%s: stk500v2_set_varef(): cannot obtain V[target]\n", + progname); + return -1; + } + + if (uaref > utarg) { + fprintf(stderr, + "%s: stk500v2_set_varef(): V[aref] must not be greater than " + "V[target] = %.1f\n", + progname, utarg / 10.0); + return -1; + } + return stk500v2_setparm(pgm, PARAM_VADJUST, uaref); +} + + +static int stk500v2_set_fosc(PROGRAMMER * pgm, double v) +{ + int fosc; + unsigned char prescale, cmatch; + static unsigned ps[] = { + 1, 8, 32, 64, 128, 256, 1024 + }; + int idx, rc; + + prescale = cmatch = 0; + if (v > 0.0) { + if (v > STK500V2_XTAL / 2) { + const char *unit; + if (v > 1e6) { + v /= 1e6; + unit = "MHz"; + } else if (v > 1e3) { + v /= 1e3; + unit = "kHz"; + } else + unit = "Hz"; + fprintf(stderr, + "%s: stk500v2_set_fosc(): f = %.3f %s too high, using %.3f MHz\n", + progname, v, unit, STK500V2_XTAL / 2e6); + fosc = STK500V2_XTAL / 2; + } else + fosc = (unsigned)v; + + for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { + if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) { + /* this prescaler value can handle our frequency */ + prescale = idx + 1; + cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1; + break; + } + } + if (idx == sizeof(ps) / sizeof(ps[0])) { + fprintf(stderr, "%s: stk500v2_set_fosc(): f = %u Hz too low, %u Hz min\n", + progname, fosc, STK500V2_XTAL / (256 * 1024 * 2)); + return -1; + } + } + + if ((rc = stk500v2_setparm(pgm, PARAM_OSC_PSCALE, prescale)) != 0 + || (rc = stk500v2_setparm(pgm, PARAM_OSC_CMATCH, cmatch)) != 0) + return rc; + + return 0; +} + +/* The list of SCK frequencies supported by the AVRISP mkII, as listed + * in AVR069 */ +static double avrispmkIIfreqs[] = { + 8000000, 4000000, 2000000, 1000000, 500000, 250000, 125000, + 96386, 89888, 84211, 79208, 74767, 70797, 67227, 64000, + 61069, 58395, 55945, 51613, 49690, 47905, 46243, 43244, + 41885, 39409, 38278, 36200, 34335, 32654, 31129, 29740, + 28470, 27304, 25724, 24768, 23461, 22285, 21221, 20254, + 19371, 18562, 17583, 16914, 16097, 15356, 14520, 13914, + 13224, 12599, 12031, 11511, 10944, 10431, 9963, 9468, + 9081, 8612, 8239, 7851, 7498, 7137, 6809, 6478, 6178, + 5879, 5607, 5359, 5093, 4870, 4633, 4418, 4209, 4019, + 3823, 3645, 3474, 3310, 3161, 3011, 2869, 2734, 2611, + 2484, 2369, 2257, 2152, 2052, 1956, 1866, 1779, 1695, + 1615, 1539, 1468, 1398, 1333, 1271, 1212, 1155, 1101, + 1049, 1000, 953, 909, 866, 826, 787, 750, 715, 682, + 650, 619, 590, 563, 536, 511, 487, 465, 443, 422, + 402, 384, 366, 349, 332, 317, 302, 288, 274, 261, + 249, 238, 226, 216, 206, 196, 187, 178, 170, 162, + 154, 147, 140, 134, 128, 122, 116, 111, 105, 100, + 95.4, 90.9, 86.6, 82.6, 78.7, 75.0, 71.5, 68.2, + 65.0, 61.9, 59.0, 56.3, 53.6, 51.1 +}; + +static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v) +{ + int i; + + for (i = 0; i < sizeof(avrispmkIIfreqs); i++) { + if (1 / avrispmkIIfreqs[i] >= v) + break; + } + + if (verbose > 2) + fprintf(stderr, "Using p = %.2f us for SCK (param = %d)\n", + 1000000 / avrispmkIIfreqs[i], i); + + return stk500v2_setparm(pgm, PARAM_SCK_DURATION, i); +} + +/* + * Return the "mode" value for the parallel and HVSP modes that + * corresponds to the pagesize. + */ +static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize) +{ + switch (pagesize) + { + case 256: return 0u << 1; + case 2: return 1u << 1; + case 4: return 2u << 1; + case 8: return 3u << 1; + case 16: return 4u << 1; + case 32: return 5u << 1; + case 64: return 6u << 1; + case 128: return 7u << 1; + } + fprintf(stderr, + "%s: stk500v2_mode_for_pagesize(): invalid pagesize: %u\n", + progname, pagesize); + exit(1); +} + +/* This code assumes that each count of the SCK duration parameter + represents 8/f, where f is the clock frequency of the STK500V2 master + processors (not the target). This number comes from Atmel + application note AVR061. It appears that the STK500V2 bit bangs SCK. + For small duration values, the actual SCK width is larger than + expected. As the duration value increases, the SCK width error + diminishes. */ +static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v) +{ + unsigned char dur; + double min, max; + + min = 8.0 / STK500V2_XTAL; + max = 255 * min; + dur = v / min + 0.5; + + if (v < min) { + dur = 1; + fprintf(stderr, + "%s: stk500v2_set_sck_period(): p = %.1f us too small, using %.1f us\n", + progname, v / 1e-6, dur * min / 1e-6); + } else if (v > max) { + dur = 255; + fprintf(stderr, + "%s: stk500v2_set_sck_period(): p = %.1f us too large, using %.1f us\n", + progname, v / 1e-6, dur * min / 1e-6); + } + + return stk500v2_setparm(pgm, PARAM_SCK_DURATION, dur); +} + + +static int stk600_set_vtarget(PROGRAMMER * pgm, double v) +{ + unsigned char utarg; + unsigned int uaref; + int rv; + + utarg = (unsigned)((v + 0.049) * 10); + + if (stk500v2_getparm2(pgm, PARAM2_AREF0, &uaref) != 0) { + fprintf(stderr, + "%s: stk500v2_set_vtarget(): cannot obtain V[aref][0]\n", + progname); + return -1; + } + + if (uaref > (unsigned)utarg * 10) { + fprintf(stderr, + "%s: stk500v2_set_vtarget(): reducing V[aref][0] from %.2f to %.1f\n", + progname, uaref / 100.0, v); + uaref = 10 * (unsigned)utarg; + if (stk500v2_setparm2(pgm, PARAM2_AREF0, uaref) + != 0) + return -1; + } + + if (stk500v2_getparm2(pgm, PARAM2_AREF1, &uaref) != 0) { + fprintf(stderr, + "%s: stk500v2_set_vtarget(): cannot obtain V[aref][1]\n", + progname); + return -1; + } + + if (uaref > (unsigned)utarg * 10) { + fprintf(stderr, + "%s: stk500v2_set_vtarget(): reducing V[aref][1] from %.2f to %.1f\n", + progname, uaref / 100.0, v); + uaref = 10 * (unsigned)utarg; + if (stk500v2_setparm2(pgm, PARAM2_AREF1, uaref) + != 0) + return -1; + } + + /* + * Vtarget on the STK600 can only be adjusted while not being in + * programming mode. + */ + if (PDATA(pgm)->lastpart) + pgm->disable(pgm); + rv = stk500v2_setparm(pgm, PARAM_VTARGET, utarg); + if (PDATA(pgm)->lastpart) + pgm->program_enable(pgm, PDATA(pgm)->lastpart); + + return rv; +} + + +static int stk600_set_varef(PROGRAMMER * pgm, unsigned int chan, double v) +{ + unsigned char utarg; + unsigned int uaref; + + uaref = (unsigned)((v + 0.0049) * 100); + + if (stk500v2_getparm(pgm, PARAM_VTARGET, &utarg) != 0) { + fprintf(stderr, + "%s: stk500v2_set_varef(): cannot obtain V[target]\n", + progname); + return -1; + } + + if (uaref > (unsigned)utarg * 10) { + fprintf(stderr, + "%s: stk500v2_set_varef(): V[aref] must not be greater than " + "V[target] = %.1f\n", + progname, utarg / 10.0); + return -1; + } + + switch (chan) + { + case 0: + return stk500v2_setparm2(pgm, PARAM2_AREF0, uaref); + + case 1: + return stk500v2_setparm2(pgm, PARAM2_AREF1, uaref); + + default: + fprintf(stderr, + "%s: stk500v2_set_varef(): invalid channel %d\n", + progname, chan); + return -1; + } +} + + +static int stk600_set_fosc(PROGRAMMER * pgm, double v) +{ + unsigned int oct, dac; + + oct = 1.443 * log(v / 1039.0); + dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v; + + return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2)); +} + +static int stk600_set_sck_period(PROGRAMMER * pgm, double v) +{ + unsigned int sck; + + sck = ceil((16e6 / (2 * 1.0 / v)) - 1); + + if (sck >= 4096) + sck = 4095; + + return stk500v2_setparm2(pgm, PARAM2_SCK_DURATION, sck); +} + + +static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value) +{ + unsigned char buf[32]; + + buf[0] = CMD_GET_PARAMETER; + buf[1] = parm; + + if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) { + fprintf(stderr,"%s: stk500v2_getparm(): failed to get parameter 0x%02x\n", + progname, parm); + return -1; + } + + *value = buf[2]; + + return 0; +} + +static int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned char value) +{ + unsigned char buf[32]; + + buf[0] = CMD_SET_PARAMETER; + buf[1] = parm; + buf[2] = value; + + if (stk500v2_command(pgm, buf, 3, sizeof(buf)) < 0) { + fprintf(stderr, "\n%s: stk500v2_setparm(): failed to set parameter 0x%02x\n", + progname, parm); + return -1; + } + + return 0; +} + +static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value) +{ + unsigned char current_value; + int res; + + res = stk500v2_getparm(pgm, parm, ¤t_value); + if (res < 0) + fprintf(stderr, "%s: Unable to get parameter 0x%02x\n", progname, parm); + + // don't issue a write if the correct value is already set. + if (value == current_value && verbose > 2) { + fprintf(stderr, "%s: Skipping paramter write; parameter value already set.\n", progname); + return 0; + } + + return stk500v2_setparm_real(pgm, parm, value); +} + +static int stk500v2_getparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int * value) +{ + unsigned char buf[32]; + + buf[0] = CMD_GET_PARAMETER; + buf[1] = parm; + + if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) { + fprintf(stderr,"%s: stk500v2_getparm2(): failed to get parameter 0x%02x\n", + progname, parm); + return -1; + } + + *value = ((unsigned)buf[2] << 8) | buf[3]; + + return 0; +} + +static int stk500v2_setparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int value) +{ + unsigned char buf[32]; + + buf[0] = CMD_SET_PARAMETER; + buf[1] = parm; + buf[2] = value >> 8; + buf[3] = value; + + if (stk500v2_command(pgm, buf, 4, sizeof(buf)) < 0) { + fprintf(stderr, "\n%s: stk500v2_setparm2(): failed to set parameter 0x%02x\n", + progname, parm); + return -1; + } + + return 0; +} + +static const char *stk600_get_cardname(const struct carddata *table, + size_t nele, int id) +{ + const struct carddata *cdp; + + if (id == 0xFF) + /* 0xFF means this card is not present at all. */ + return "Not present"; + + for (cdp = table; nele > 0; cdp++, nele--) + if (cdp->id == id) + return cdp->name; + + return "Unknown"; +} + + +static void stk500v2_display(PROGRAMMER * pgm, const char * p) +{ + unsigned char maj, min, hdw, topcard, maj_s1, min_s1, maj_s2, min_s2; + unsigned int rev; + const char *topcard_name, *pgmname; + + switch (PDATA(pgm)->pgmtype) { + case PGMTYPE_UNKNOWN: pgmname = "Unknown"; break; + case PGMTYPE_STK500: pgmname = "STK500"; break; + case PGMTYPE_AVRISP: pgmname = "AVRISP"; break; + case PGMTYPE_AVRISP_MKII: pgmname = "AVRISP mkII"; break; + case PGMTYPE_STK600: pgmname = "STK600"; break; + default: pgmname = "None"; + } + if (PDATA(pgm)->pgmtype != PGMTYPE_JTAGICE_MKII) { + fprintf(stderr, "%sProgrammer Model: %s\n", p, pgmname); + stk500v2_getparm(pgm, PARAM_HW_VER, &hdw); + stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj); + stk500v2_getparm(pgm, PARAM_SW_MINOR, &min); + fprintf(stderr, "%sHardware Version: %d\n", p, hdw); + fprintf(stderr, "%sFirmware Version Master : %d.%02d\n", p, maj, min); + if (PDATA(pgm)->pgmtype == PGMTYPE_STK600) { + stk500v2_getparm(pgm, PARAM_SW_MAJOR_SLAVE1, &maj_s1); + stk500v2_getparm(pgm, PARAM_SW_MINOR_SLAVE1, &min_s1); + stk500v2_getparm(pgm, PARAM_SW_MAJOR_SLAVE2, &maj_s2); + stk500v2_getparm(pgm, PARAM_SW_MINOR_SLAVE2, &min_s2); + fprintf(stderr, "%sFirmware Version Slave 1: %d.%02d\n", p, maj_s1, min_s1); + fprintf(stderr, "%sFirmware Version Slave 2: %d.%02d\n", p, maj_s2, min_s2); + } + } + + if (PDATA(pgm)->pgmtype == PGMTYPE_STK500) { + stk500v2_getparm(pgm, PARAM_TOPCARD_DETECT, &topcard); + switch (topcard) { + case 0xAA: topcard_name = "STK501"; break; + case 0x55: topcard_name = "STK502"; break; + case 0xFA: topcard_name = "STK503"; break; + case 0xEE: topcard_name = "STK504"; break; + case 0xE4: topcard_name = "STK505"; break; + case 0xDD: topcard_name = "STK520"; break; + default: topcard_name = "Unknown"; break; + } + fprintf(stderr, "%sTopcard : %s\n", p, topcard_name); + } else if (PDATA(pgm)->pgmtype == PGMTYPE_STK600) { + stk500v2_getparm(pgm, PARAM_ROUTINGCARD_ID, &topcard); + fprintf(stderr, "%sRouting card : %s\n", p, + stk600_get_cardname(routing_cards, + sizeof routing_cards / sizeof routing_cards[0], + topcard)); + stk500v2_getparm(pgm, PARAM_SOCKETCARD_ID, &topcard); + fprintf(stderr, "%sSocket card : %s\n", p, + stk600_get_cardname(socket_cards, + sizeof socket_cards / sizeof socket_cards[0], + topcard)); + stk500v2_getparm2(pgm, PARAM2_RC_ID_TABLE_REV, &rev); + fprintf(stderr, "%sRC_ID table rev : %d\n", p, rev); + stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev); + fprintf(stderr, "%sEC_ID table rev : %d\n", p, rev); + } + stk500v2_print_parms1(pgm, p); + + return; +} + +static double +f_to_kHz_MHz(double f, const char **unit) +{ + if (f > 1e6) { + f /= 1e6; + *unit = "MHz"; + } else if (f > 1e3) { + f /= 1000; + *unit = "kHz"; + } else + *unit = "Hz"; + + return f; +} + +static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p) +{ + unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration; + unsigned int sck_stk600, clock_conf, dac, oct, varef; + unsigned char vtarget_jtag[4]; + int prescale; + double f; + const char *unit; + void *mycookie; + + if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) { + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget_jtag); + pgm->cookie = mycookie; + fprintf(stderr, "%sVtarget : %.1f V\n", p, + b2_to_u16(vtarget_jtag) / 1000.0); + } else { + stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget); + fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0); + } + + switch (PDATA(pgm)->pgmtype) { + case PGMTYPE_STK500: + stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration); + stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust); + stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale); + stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch); + fprintf(stderr, "%sSCK period : %.1f us\n", p, + sck_duration * 8.0e6 / STK500V2_XTAL + 0.05); + fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0); + fprintf(stderr, "%sOscillator : ", p); + if (osc_pscale == 0) + fprintf(stderr, "Off\n"); + else { + prescale = 1; + f = STK500V2_XTAL / 2; + + switch (osc_pscale) { + case 2: prescale = 8; break; + case 3: prescale = 32; break; + case 4: prescale = 64; break; + case 5: prescale = 128; break; + case 6: prescale = 256; break; + case 7: prescale = 1024; break; + } + f /= prescale; + f /= (osc_cmatch + 1); + f = f_to_kHz_MHz(f, &unit); + fprintf(stderr, "%.3f %s\n", f, unit); + } + break; + + case PGMTYPE_AVRISP_MKII: + case PGMTYPE_JTAGICE_MKII: + stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration); + fprintf(stderr, "%sSCK period : %.2f us\n", p, + (float) 1000000 / avrispmkIIfreqs[sck_duration]); + break; + + case PGMTYPE_STK600: + stk500v2_getparm2(pgm, PARAM2_AREF0, &varef); + fprintf(stderr, "%sVaref 0 : %.2f V\n", p, varef / 100.0); + stk500v2_getparm2(pgm, PARAM2_AREF1, &varef); + fprintf(stderr, "%sVaref 1 : %.2f V\n", p, varef / 100.0); + stk500v2_getparm2(pgm, PARAM2_SCK_DURATION, &sck_stk600); + fprintf(stderr, "%sSCK period : %.2f us\n", p, + (float) (sck_stk600 + 1) / 8.0); + stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf); + oct = (clock_conf & 0xf000) >> 12u; + dac = (clock_conf & 0x0ffc) >> 2u; + f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0); + f = f_to_kHz_MHz(f, &unit); + fprintf(stderr, "%sOscillator : %.3f %s\n", + p, f, unit); + break; + + default: + fprintf(stderr, "%sSCK period : %.1f us\n", p, + sck_duration * 8.0e6 / STK500V2_XTAL + 0.05); + break; + } + + return; +} + + +static void stk500v2_print_parms(PROGRAMMER * pgm) +{ + stk500v2_print_parms1(pgm, ""); +} + +static int stk500v2_perform_osccal(PROGRAMMER * pgm) +{ + unsigned char buf[32]; + int rv; + + buf[0] = CMD_OSCCAL; + + rv = stk500v2_command(pgm, buf, 1, sizeof(buf)); + if (rv < 0) { + fprintf(stderr, "%s: stk500v2_perform_osccal(): failed\n", + progname); + return -1; + } + + return 0; +} + +/* + * Wrapper functions for the JTAG ICE mkII in ISP mode. This mode + * uses the normal JTAG ICE mkII packet stream to communicate with the + * ICE, but then encapsulates AVRISP mkII commands using + * CMND_ISP_PACKET. + */ + +/* + * Open a JTAG ICE mkII in ISP mode. + */ +static int stk500v2_jtagmkII_open(PROGRAMMER * pgm, char * port) +{ + long baud; + void *mycookie; + int rv; + + if (verbose >= 2) + fprintf(stderr, "%s: stk500v2_jtagmkII_open()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_JTAGICEMKII; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + stk500v2_drain(pgm, 0); + + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + if ((rv = jtagmkII_getsync(pgm, EMULATOR_MODE_SPI)) != 0) { + if (rv != JTAGII_GETSYNC_FAIL_GRACEFUL) + fprintf(stderr, + "%s: failed to sync with the JTAG ICE mkII in ISP mode\n", + progname); + pgm->cookie = mycookie; + return -1; + } + pgm->cookie = mycookie; + + PDATA(pgm)->pgmtype = PGMTYPE_JTAGICE_MKII; + + if (pgm->bitclock != 0.0) { + if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + return 0; +} + + +/* + * Close an AVR Dragon or JTAG ICE mkII in ISP/HVSP/PP mode. + */ +static void stk500v2_jtagmkII_close(PROGRAMMER * pgm) +{ + void *mycookie; + + if (verbose >= 2) + fprintf(stderr, "%s: stk500v2_jtagmkII_close()\n", progname); + + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + jtagmkII_close(pgm); + pgm->cookie = mycookie; +} + + +/* + * Wrapper functions for the AVR Dragon in ISP mode. This mode + * uses the normal JTAG ICE mkII packet stream to communicate with the + * ICE, but then encapsulates AVRISP mkII commands using + * CMND_ISP_PACKET. + */ + +/* + * Open an AVR Dragon in ISP mode. + */ +static int stk500v2_dragon_isp_open(PROGRAMMER * pgm, char * port) +{ + long baud; + void *mycookie; + + if (verbose >= 2) + fprintf(stderr, "%s: stk500v2_dragon_isp_open()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_AVRDRAGON; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + stk500v2_drain(pgm, 0); + + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + if (jtagmkII_getsync(pgm, EMULATOR_MODE_SPI) != 0) { + fprintf(stderr, "%s: failed to sync with the AVR Dragon in ISP mode\n", + progname); + pgm->cookie = mycookie; + return -1; + } + pgm->cookie = mycookie; + + PDATA(pgm)->pgmtype = PGMTYPE_JTAGICE_MKII; + + if (pgm->bitclock != 0.0) { + if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + return 0; +} + + +/* + * Wrapper functions for the AVR Dragon in HV mode. This mode + * uses the normal JTAG ICE mkII packet stream to communicate with the + * ICE, but then encapsulates AVRISP mkII commands using + * CMND_ISP_PACKET. + */ + +/* + * Open an AVR Dragon in HV mode (HVSP or parallel). + */ +static int stk500v2_dragon_hv_open(PROGRAMMER * pgm, char * port) +{ + long baud; + void *mycookie; + + if (verbose >= 2) + fprintf(stderr, "%s: stk500v2_dragon_hv_open()\n", progname); + + /* + * The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon + * attaching. If the config file or command-line parameters specify + * a higher baud rate, we switch to it later on, after establishing + * the connection with the ICE. + */ + baud = 19200; + + /* + * If the port name starts with "usb", divert the serial routines + * to the USB ones. The serial_open() function for USB overrides + * the meaning of the "baud" parameter to be the USB device ID to + * search for. + */ + if (strncmp(port, "usb", 3) == 0) { +#if defined(HAVE_LIBUSB) + serdev = &usb_serdev; + baud = USB_DEVICE_AVRDRAGON; +#else + fprintf(stderr, "avrdude was compiled without usb support.\n"); + return -1; +#endif + } + + strcpy(pgm->port, port); + if (serial_open(port, baud, &pgm->fd)==-1) { + return -1; + } + + /* + * drain any extraneous input + */ + stk500v2_drain(pgm, 0); + + mycookie = pgm->cookie; + pgm->cookie = PDATA(pgm)->chained_pdata; + if (jtagmkII_getsync(pgm, EMULATOR_MODE_HV) != 0) { + fprintf(stderr, "%s: failed to sync with the AVR Dragon in HV mode\n", + progname); + pgm->cookie = mycookie; + return -1; + } + pgm->cookie = mycookie; + + PDATA(pgm)->pgmtype = PGMTYPE_JTAGICE_MKII; + + if (pgm->bitclock != 0.0) { + if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + return 0; +} + +/* + * XPROG wrapper + */ +static int stk600_xprog_command(PROGRAMMER * pgm, unsigned char *b, + unsigned int cmdsize, unsigned int responsesize) +{ + unsigned char *newb; + unsigned int s; + int rv; + + if (cmdsize < responsesize) + s = responsesize; + else + s = cmdsize; + + if ((newb = malloc(s + 1)) == 0) { + fprintf(stderr, "%s: stk600_xprog_cmd(): out of memory\n", + progname); + return -1; + } + + newb[0] = CMD_XPROG; + memcpy(newb + 1, b, cmdsize); + rv = stk500v2_command(pgm, newb, cmdsize + 1, responsesize + 1); + if (rv == 0) { + memcpy(b, newb + 1, responsesize); + } + + free(newb); + + return rv; +} + + +/* + * issue the 'program enable' command to the AVR device, XPROG version + */ +static int stk600_xprog_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[16]; + unsigned int eepagesize = 42; + unsigned int nvm_base; + AVRMEM *mem = NULL; + int use_tpi; + + use_tpi = (p->flags & AVRPART_HAS_TPI) != 0; + + if (!use_tpi) { + if (p->nvm_base == 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): no nvm_base parameter for PDI device\n", + progname); + return -1; + } + if ((mem = avr_locate_mem(p, "eeprom")) != NULL) { + if (mem->page_size == 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): no EEPROM page_size parameter for PDI device\n", + progname); + return -1; + } + eepagesize = mem->page_size; + } + } + + buf[0] = CMD_XPROG_SETMODE; + buf[1] = use_tpi? XPRG_MODE_TPI: XPRG_MODE_PDI; + if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): CMD_XPROG_SETMODE(XPRG_MODE_%s) failed\n", + progname, use_tpi? "TPI": "PDI"); + return -1; + } + + buf[0] = XPRG_CMD_ENTER_PROGMODE; + if (stk600_xprog_command(pgm, buf, 1, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): XPRG_CMD_ENTER_PROGMODE failed\n", + progname); + return -1; + } + + if (use_tpi) { + /* + * Whatever all that might mean, it matches what AVR Studio + * does. + */ + if (stk500v2_setparm_real(pgm, PARAM_DISCHARGEDELAY, 232) < 0) + return -1; + + buf[0] = XPRG_CMD_SET_PARAM; + buf[1] = XPRG_PARAM_TPI_3; + buf[2] = 51; + if (stk600_xprog_command(pgm, buf, 3, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): XPRG_CMD_SET_PARAM(XPRG_PARAM_TPI_3) failed\n", + progname); + return -1; + } + + buf[0] = XPRG_CMD_SET_PARAM; + buf[1] = XPRG_PARAM_TPI_4; + buf[2] = 50; + if (stk600_xprog_command(pgm, buf, 3, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): XPRG_CMD_SET_PARAM(XPRG_PARAM_TPI_4) failed\n", + progname); + return -1; + } + } else { + buf[0] = XPRG_CMD_SET_PARAM; + buf[1] = XPRG_PARAM_NVMBASE; + nvm_base = p->nvm_base; + /* + * The 0x01000000 appears to be an indication to the programmer + * that the respective address is located in IO (i.e., SRAM) + * memory address space rather than flash. This is not documented + * anywhere in AVR079 but matches what AVR Studio does. + */ + nvm_base |= 0x01000000; + buf[2] = nvm_base >> 24; + buf[3] = nvm_base >> 16; + buf[4] = nvm_base >> 8; + buf[5] = nvm_base; + if (stk600_xprog_command(pgm, buf, 6, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): XPRG_CMD_SET_PARAM(XPRG_PARAM_NVMBASE) failed\n", + progname); + return -1; + } + + if (mem != NULL) { + buf[0] = XPRG_CMD_SET_PARAM; + buf[1] = XPRG_PARAM_EEPPAGESIZE; + buf[2] = eepagesize >> 8; + buf[3] = eepagesize; + if (stk600_xprog_command(pgm, buf, 4, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_enable(): XPRG_CMD_SET_PARAM(XPRG_PARAM_EEPPAGESIZE) failed\n", + progname); + return -1; + } + } + } + + return 0; +} + +static void stk600_xprog_disable(PROGRAMMER * pgm) +{ + unsigned char buf[2]; + + buf[0] = XPRG_CMD_LEAVE_PROGMODE; + if (stk600_xprog_command(pgm, buf, 1, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_program_disable(): XPRG_CMD_LEAVE_PROGMODE failed\n", + progname); + } +} + +static int stk600_xprog_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + unsigned char b[9 + 256]; + int need_erase = 0; + unsigned char write_size = 1; + unsigned char memcode; + + memset(b, 0, sizeof(b)); + + if (strcmp(mem->desc, "flash") == 0) { + memcode = XPRG_MEM_TYPE_APPL; + } else if (strcmp(mem->desc, "boot") == 0) { + memcode = XPRG_MEM_TYPE_BOOT; + } else if (strcmp(mem->desc, "eeprom") == 0) { + memcode = XPRG_MEM_TYPE_EEPROM; + } else if (strcmp(mem->desc, "lockbits") == 0) { + memcode = XPRG_MEM_TYPE_LOCKBITS; + } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { + memcode = XPRG_MEM_TYPE_FUSE; + if (p->flags & AVRPART_HAS_TPI) + /* + * TPI devices need a mystic erase prior to writing their + * fuses. + */ + need_erase = 1; + } else if (strcmp(mem->desc, "usersig") == 0) { + memcode = XPRG_MEM_TYPE_USERSIG; + } else { + fprintf(stderr, + "%s: stk600_xprog_write_byte(): unknown memory \"%s\"\n", + progname, mem->desc); + return -1; + } + addr += mem->offset; + + if (need_erase) { + b[0] = XPRG_CMD_ERASE; + b[1] = XPRG_ERASE_CONFIG; + b[2] = mem->offset >> 24; + b[3] = mem->offset >> 16; + b[4] = mem->offset >> 8; + b[5] = mem->offset + 1; + if (stk600_xprog_command(pgm, b, 6, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_chip_erase(): XPRG_CMD_ERASE(XPRG_ERASE_CONFIG) failed\n", + progname); + return -1; + } + } + + if (p->flags & AVRPART_HAS_TPI) { + /* + * Some TPI memories (configuration aka. fuse) require a + * larger write block size. We record that as a blocksize in + * avrdude.conf. + */ + if (mem->blocksize != 0) + write_size = mem->blocksize; + } + + b[0] = XPRG_CMD_WRITE_MEM; + b[1] = memcode; + b[2] = 0; /* pagemode: non-paged write */ + b[3] = addr >> 24; + b[4] = addr >> 16; + b[5] = addr >> 8; + b[6] = addr; + b[7] = 0; + b[8] = write_size; + b[9] = data; + if (stk600_xprog_command(pgm, b, 9 + write_size, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_write_byte(): XPRG_CMD_WRITE_MEM failed\n", + progname); + return -1; + } + return 0; +} + + +static int stk600_xprog_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + unsigned char b[8]; + + if (strcmp(mem->desc, "flash") == 0) { + b[1] = XPRG_MEM_TYPE_APPL; + } else if (strcmp(mem->desc, "boot") == 0) { + b[1] = XPRG_MEM_TYPE_BOOT; + } else if (strcmp(mem->desc, "eeprom") == 0) { + b[1] = XPRG_MEM_TYPE_EEPROM; + } else if (strcmp(mem->desc, "signature") == 0) { + b[1] = XPRG_MEM_TYPE_APPL; + } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { + b[1] = XPRG_MEM_TYPE_FUSE; + } else if (strcmp(mem->desc, "lockbits") == 0) { + b[1] = XPRG_MEM_TYPE_LOCKBITS; + } else if (strcmp(mem->desc, "calibration") == 0) { + b[1] = XPRG_MEM_TYPE_FACTORY_CALIBRATION; + } else if (strcmp(mem->desc, "usersig") == 0) { + b[1] = XPRG_MEM_TYPE_USERSIG; + } else { + fprintf(stderr, + "%s: stk600_xprog_read_byte(): unknown memory \"%s\"\n", + progname, mem->desc); + return -1; + } + addr += mem->offset; + + b[0] = XPRG_CMD_READ_MEM; + b[2] = addr >> 24; + b[3] = addr >> 16; + b[4] = addr >> 8; + b[5] = addr; + b[6] = 0; + b[7] = 1; + if (stk600_xprog_command(pgm, b, 8, 3) < 0) { + fprintf(stderr, + "%s: stk600_xprog_read_byte(): XPRG_CMD_READ_MEM failed\n", + progname); + return -1; + } + *value = b[2]; + return 0; +} + + +static int stk600_xprog_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + int page_size, int n_bytes) +{ + unsigned char *b; + unsigned int addr; + unsigned int offset; + unsigned char memtype; + int n_bytes_orig = n_bytes; + unsigned long use_ext_addr = 0; + + /* + * The XPROG read command supports at most 256 bytes in one + * transfer. + */ + if (page_size > 256) + page_size = 256; /* not really a page size anymore */ + + /* + * Fancy offsets everywhere. + * This is probably what AVR079 means when writing about the + * "TIF address space". + */ + if (strcmp(mem->desc, "flash") == 0) { + memtype = XPRG_MEM_TYPE_APPL; + if (mem->size > 64 * 1024) + use_ext_addr = (1UL << 31); + } else if (strcmp(mem->desc, "boot") == 0) { + memtype = XPRG_MEM_TYPE_BOOT; + // Do we have to consider the total amount of flash + // instead to decide whether to use extended addressing? + if (mem->size > 64 * 1024) + use_ext_addr = (1UL << 31); + } else if (strcmp(mem->desc, "eeprom") == 0) { + memtype = XPRG_MEM_TYPE_EEPROM; + } else { + fprintf(stderr, + "%s: stk600_xprog_paged_load(): unknown paged memory \"%s\"\n", + progname, mem->desc); + return -1; + } + addr = mem->offset; + + if ((b = malloc(page_size + 2)) == NULL) { + fprintf(stderr, + "%s: stk600_xprog_paged_load(): out of memory\n", + progname); + return -1; + } + + if (stk500v2_loadaddr(pgm, use_ext_addr) < 0) + return -1; + + offset = 0; + while (n_bytes != 0) { + report_progress(offset, n_bytes_orig, NULL); + b[0] = XPRG_CMD_READ_MEM; + b[1] = memtype; + b[2] = addr >> 24; + b[3] = addr >> 16; + b[4] = addr >> 8; + b[5] = addr; + b[6] = page_size >> 8; + b[7] = page_size; + if (stk600_xprog_command(pgm, b, 8, page_size + 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_paged_load(): XPRG_CMD_READ_MEM failed\n", + progname); + return -1; + } + memcpy(mem->buf + offset, b + 2, page_size); + if (n_bytes < page_size) { + n_bytes = page_size; + } + offset += page_size; + addr += page_size; + n_bytes -= page_size; + } + free(b); + + return n_bytes_orig; +} + +static int stk600_xprog_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + int page_size, int n_bytes) +{ + unsigned char *b; + unsigned int addr; + unsigned int offset; + unsigned char memtype; + int n_bytes_orig = n_bytes; + size_t writesize; + unsigned long use_ext_addr = 0; + unsigned char writemode; + + /* + * The XPROG read command supports at most 256 bytes in one + * transfer. + */ + if (page_size > 512) { + fprintf(stderr, + "%s: stk600_xprog_paged_write(): cannot handle page size > 512\n", + progname); + return -1; + } + + /* + * Fancy offsets everywhere. + * This is probably what AVR079 means when writing about the + * "TIF address space". + */ + if (strcmp(mem->desc, "flash") == 0) { + memtype = XPRG_MEM_TYPE_APPL; + writemode = (1 << XPRG_MEM_WRITE_WRITE); + if (mem->size > 64 * 1024) + use_ext_addr = (1UL << 31); + } else if (strcmp(mem->desc, "boot") == 0) { + memtype = XPRG_MEM_TYPE_BOOT; + writemode = (1 << XPRG_MEM_WRITE_WRITE); + // Do we have to consider the total amount of flash + // instead to decide whether to use extended addressing? + if (mem->size > 64 * 1024) + use_ext_addr = (1UL << 31); + } else if (strcmp(mem->desc, "eeprom") == 0) { + memtype = XPRG_MEM_TYPE_EEPROM; + writemode = (1 << XPRG_MEM_WRITE_WRITE) | (1 << XPRG_MEM_WRITE_ERASE); + } else { + fprintf(stderr, + "%s: stk600_xprog_paged_write(): unknown paged memory \"%s\"\n", + progname, mem->desc); + return -1; + } + addr = mem->offset; + + if ((b = malloc(page_size + 9)) == NULL) { + fprintf(stderr, + "%s: stk600_xprog_paged_write(): out of memory\n", + progname); + return -1; + } + + if (stk500v2_loadaddr(pgm, use_ext_addr) < 0) + return -1; + + offset = 0; + while (n_bytes != 0) { + report_progress(offset, n_bytes_orig, NULL); + + if (page_size > 256) { + /* + * AVR079 is not quite clear. While it suggests that + * downloading up to 512 bytes (256 words) were OK, it + * obviously isn't -- 512-byte pages on the ATxmega128A1 + * are getting corrupted when written as a single piece. + * It writes random junk somewhere beyond byte 256. + * Splitting it into 256 byte chunks, and only setting the + * erase page / write page bits in the final chunk helps. + */ + if (page_size % 256 != 0) { + fprintf(stderr, + "%s: stk600_xprog_paged_write(): page size not multiple of 256\n", + progname); + return -1; + } + unsigned int chunk; + for (chunk = 0; chunk < page_size; chunk += 256) { + if (n_bytes < 256) { + memset(b + 9 + n_bytes, 0xff, 256 - n_bytes); + writesize = n_bytes; + } else { + writesize = 256; + } + b[0] = XPRG_CMD_WRITE_MEM; + b[1] = memtype; + if (chunk + 256 == page_size) { + b[2] = writemode; /* last chunk */ + } else { + b[2] = 0; /* initial/intermediate chunk: just download */ + } + b[3] = addr >> 24; + b[4] = addr >> 16; + b[5] = addr >> 8; + b[6] = addr; + b[7] = 1; + b[8] = 0; + memcpy(b + 9, mem->buf + offset, writesize); + if (stk600_xprog_command(pgm, b, 256 + 9, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_paged_write(): XPRG_CMD_WRITE_MEM failed\n", + progname); + return -1; + } + if (n_bytes < 256) + n_bytes = 256; + + offset += 256; + addr += 256; + n_bytes -= 256; + } + } else { + if (n_bytes < page_size) { + /* + * This can easily happen if the input file was not a + * multiple of the page size. + */ + memset(b + 9 + n_bytes, 0xff, page_size - n_bytes); + writesize = n_bytes; + } else { + writesize = page_size; + } + b[0] = XPRG_CMD_WRITE_MEM; + b[1] = memtype; + b[2] = writemode; + b[3] = addr >> 24; + b[4] = addr >> 16; + b[5] = addr >> 8; + b[6] = addr; + b[7] = page_size >> 8; + b[8] = page_size; + memcpy(b + 9, mem->buf + offset, writesize); + if (stk600_xprog_command(pgm, b, page_size + 9, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_paged_write(): XPRG_CMD_WRITE_MEM failed\n", + progname); + return -1; + } + if (n_bytes < page_size) + n_bytes = page_size; + + offset += page_size; + addr += page_size; + n_bytes -= page_size; + } + } + free(b); + + return n_bytes_orig; +} + +static int stk600_xprog_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char b[6]; + AVRMEM *mem; + unsigned int addr = 0; + + if (p->flags & AVRPART_HAS_TPI) { + if ((mem = avr_locate_mem(p, "flash")) == NULL) { + fprintf(stderr, + "%s: stk600_xprog_chip_erase(): no FLASH definition found for TPI device\n", + progname); + return -1; + } + addr = mem->offset + 1; + } + + b[0] = XPRG_CMD_ERASE; + b[1] = XPRG_ERASE_CHIP; + b[2] = addr >> 24; + b[3] = addr >> 16; + b[4] = addr >> 8; + b[5] = addr; + if (stk600_xprog_command(pgm, b, 6, 2) < 0) { + fprintf(stderr, + "%s: stk600_xprog_chip_erase(): XPRG_CMD_ERASE(XPRG_ERASE_CHIP) failed\n", + progname); + return -1; + } + return 0; +} + +/* + * Modify pgm's methods for XPROG operation. + */ +static void stk600_setup_xprog(PROGRAMMER * pgm) +{ + pgm->program_enable = stk600_xprog_program_enable; + pgm->disable = stk600_xprog_disable; + pgm->read_byte = stk600_xprog_read_byte; + pgm->write_byte = stk600_xprog_write_byte; + pgm->paged_load = stk600_xprog_paged_load; + pgm->paged_write = stk600_xprog_paged_write; + pgm->chip_erase = stk600_xprog_chip_erase; +} + + +/* + * Modify pgm's methods for ISP operation. + */ +static void stk600_setup_isp(PROGRAMMER * pgm) +{ + pgm->program_enable = stk500v2_program_enable; + pgm->disable = stk500v2_disable; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + pgm->paged_load = stk500v2_paged_load; + pgm->paged_write = stk500v2_paged_write; + pgm->chip_erase = stk500v2_chip_erase; +} + + +void stk500v2_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK500V2"); + + /* + * mandatory functions + */ + pgm->initialize = stk500v2_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500v2_disable; + pgm->program_enable = stk500v2_program_enable; + pgm->chip_erase = stk500v2_chip_erase; + pgm->cmd = stk500v2_cmd; + pgm->open = stk500v2_open; + pgm->close = stk500v2_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + pgm->paged_write = stk500v2_paged_write; + pgm->paged_load = stk500v2_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk500v2_set_vtarget; + pgm->set_varef = stk500v2_set_varef; + pgm->set_fosc = stk500v2_set_fosc; + pgm->set_sck_period = stk500v2_set_sck_period; + pgm->perform_osccal = stk500v2_perform_osccal; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; + pgm->page_size = 256; +} + +void stk500pp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK500PP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500pp_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500pp_disable; + pgm->program_enable = stk500pp_program_enable; + pgm->chip_erase = stk500pp_chip_erase; + pgm->open = stk500v2_open; + pgm->close = stk500v2_close; + pgm->read_byte = stk500pp_read_byte; + pgm->write_byte = stk500pp_write_byte; + + /* + * optional functions + */ + pgm->paged_write = stk500pp_paged_write; + pgm->paged_load = stk500pp_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk500v2_set_vtarget; + pgm->set_varef = stk500v2_set_varef; + pgm->set_fosc = stk500v2_set_fosc; + pgm->set_sck_period = stk500v2_set_sck_period; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; + pgm->page_size = 256; +} + +void stk500hvsp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK500HVSP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500hvsp_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500hvsp_disable; + pgm->program_enable = stk500hvsp_program_enable; + pgm->chip_erase = stk500hvsp_chip_erase; + pgm->open = stk500v2_open; + pgm->close = stk500v2_close; + pgm->read_byte = stk500hvsp_read_byte; + pgm->write_byte = stk500hvsp_write_byte; + + /* + * optional functions + */ + pgm->paged_write = stk500hvsp_paged_write; + pgm->paged_load = stk500hvsp_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk500v2_set_vtarget; + pgm->set_varef = stk500v2_set_varef; + pgm->set_fosc = stk500v2_set_fosc; + pgm->set_sck_period = stk500v2_set_sck_period; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; + pgm->page_size = 256; +} + +void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKII_ISP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500v2_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500v2_disable; + pgm->program_enable = stk500v2_program_enable; + pgm->chip_erase = stk500v2_chip_erase; + pgm->cmd = stk500v2_cmd; + pgm->open = stk500v2_jtagmkII_open; + pgm->close = stk500v2_jtagmkII_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + pgm->paged_write = stk500v2_paged_write; + pgm->paged_load = stk500v2_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->perform_osccal = stk500v2_perform_osccal; + pgm->setup = stk500v2_jtagmkII_setup; + pgm->teardown = stk500v2_jtagmkII_teardown; + pgm->page_size = 256; +} + +void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_ISP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500v2_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500v2_disable; + pgm->program_enable = stk500v2_program_enable; + pgm->chip_erase = stk500v2_chip_erase; + pgm->cmd = stk500v2_cmd; + pgm->open = stk500v2_dragon_isp_open; + pgm->close = stk500v2_jtagmkII_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + pgm->paged_write = stk500v2_paged_write; + pgm->paged_load = stk500v2_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->setup = stk500v2_jtagmkII_setup; + pgm->teardown = stk500v2_jtagmkII_teardown; + pgm->page_size = 256; +} + +void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_PP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500pp_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500pp_disable; + pgm->program_enable = stk500pp_program_enable; + pgm->chip_erase = stk500pp_chip_erase; + pgm->open = stk500v2_dragon_hv_open; + pgm->close = stk500v2_jtagmkII_close; + pgm->read_byte = stk500pp_read_byte; + pgm->write_byte = stk500pp_write_byte; + + /* + * optional functions + */ + pgm->paged_write = stk500pp_paged_write; + pgm->paged_load = stk500pp_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk500v2_set_vtarget; + pgm->set_varef = stk500v2_set_varef; + pgm->set_fosc = stk500v2_set_fosc; + pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->setup = stk500v2_jtagmkII_setup; + pgm->teardown = stk500v2_jtagmkII_teardown; + pgm->page_size = 256; +} + +void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_HVSP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500hvsp_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500hvsp_disable; + pgm->program_enable = stk500hvsp_program_enable; + pgm->chip_erase = stk500hvsp_chip_erase; + pgm->open = stk500v2_dragon_hv_open; + pgm->close = stk500v2_jtagmkII_close; + pgm->read_byte = stk500hvsp_read_byte; + pgm->write_byte = stk500hvsp_write_byte; + + /* + * optional functions + */ + pgm->paged_write = stk500hvsp_paged_write; + pgm->paged_load = stk500hvsp_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk500v2_set_vtarget; + pgm->set_varef = stk500v2_set_varef; + pgm->set_fosc = stk500v2_set_fosc; + pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->setup = stk500v2_jtagmkII_setup; + pgm->teardown = stk500v2_jtagmkII_teardown; + pgm->page_size = 256; +} + +void stk600_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK600"); + + /* + * mandatory functions + */ + pgm->initialize = stk500v2_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500v2_disable; + pgm->program_enable = stk500v2_program_enable; + pgm->chip_erase = stk500v2_chip_erase; + pgm->cmd = stk500v2_cmd; + pgm->open = stk600_open; + pgm->close = stk500v2_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + pgm->paged_write = stk500v2_paged_write; + pgm->paged_load = stk500v2_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk600_set_vtarget; + pgm->set_varef = stk600_set_varef; + pgm->set_fosc = stk600_set_fosc; + pgm->set_sck_period = stk600_set_sck_period; + pgm->perform_osccal = stk500v2_perform_osccal; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; + pgm->page_size = 256; +} + +void stk600pp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK600PP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500pp_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500pp_disable; + pgm->program_enable = stk500pp_program_enable; + pgm->chip_erase = stk500pp_chip_erase; + pgm->open = stk600_open; + pgm->close = stk500v2_close; + pgm->read_byte = stk500pp_read_byte; + pgm->write_byte = stk500pp_write_byte; + + /* + * optional functions + */ + pgm->paged_write = stk500pp_paged_write; + pgm->paged_load = stk500pp_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk600_set_vtarget; + pgm->set_varef = stk600_set_varef; + pgm->set_fosc = stk600_set_fosc; + pgm->set_sck_period = stk600_set_sck_period; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; + pgm->page_size = 256; +} + +void stk600hvsp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "STK600HVSP"); + + /* + * mandatory functions + */ + pgm->initialize = stk500hvsp_initialize; + pgm->display = stk500v2_display; + pgm->enable = stk500v2_enable; + pgm->disable = stk500hvsp_disable; + pgm->program_enable = stk500hvsp_program_enable; + pgm->chip_erase = stk500hvsp_chip_erase; + pgm->open = stk600_open; + pgm->close = stk500v2_close; + pgm->read_byte = stk500hvsp_read_byte; + pgm->write_byte = stk500hvsp_write_byte; + + /* + * optional functions + */ + pgm->paged_write = stk500hvsp_paged_write; + pgm->paged_load = stk500hvsp_paged_load; + pgm->print_parms = stk500v2_print_parms; + pgm->set_vtarget = stk600_set_vtarget; + pgm->set_varef = stk600_set_varef; + pgm->set_fosc = stk600_set_fosc; + pgm->set_sck_period = stk600_set_sck_period; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; + pgm->page_size = 256; +} + diff --git a/avrdude/stk500v2.h b/avrdude/stk500v2.h new file mode 100644 index 00000000..2278270d --- /dev/null +++ b/avrdude/stk500v2.h @@ -0,0 +1,52 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2005 Brian S. Dean + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef stk500v2_h +#define stk500v2_h + +#ifdef __cplusplus +extern "C" { +#endif + +void stk500v2_initpgm (PROGRAMMER * pgm); +void stk500hvsp_initpgm (PROGRAMMER * pgm); +void stk500pp_initpgm (PROGRAMMER * pgm); +void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm); +void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm); +void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm); +void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm); +void stk600_initpgm (PROGRAMMER * pgm); +void stk600hvsp_initpgm (PROGRAMMER * pgm); +void stk600pp_initpgm (PROGRAMMER * pgm); + +void stk500v2_setup(PROGRAMMER * pgm); +void stk500v2_teardown(PROGRAMMER * pgm); +int stk500v2_drain(PROGRAMMER * pgm, int display); +int stk500v2_getsync(PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/avrdude/stk500v2_private.h b/avrdude/stk500v2_private.h new file mode 100644 index 00000000..66a419b7 --- /dev/null +++ b/avrdude/stk500v2_private.h @@ -0,0 +1,322 @@ +//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************ +//* +//* Title: AVR068 - STK500 Communication Protocol +//* Filename: command.h +//* Version: 1.0 +//* Last updated: 10.01.2005 +//* +//* Support E-mail: avr@atmel.com +//* +//************************************************************************** + +#include "pgm.h" + +// *****************[ STK message constants ]*************************** + +#define MESSAGE_START 0x1B //= ESC = 27 decimal +#define TOKEN 0x0E + +// *****************[ STK general command constants ]************************** + +#define CMD_SIGN_ON 0x01 +#define CMD_SET_PARAMETER 0x02 +#define CMD_GET_PARAMETER 0x03 +#define CMD_SET_DEVICE_PARAMETERS 0x04 +#define CMD_OSCCAL 0x05 +#define CMD_LOAD_ADDRESS 0x06 +#define CMD_FIRMWARE_UPGRADE 0x07 +#define CMD_CHECK_TARGET_CONNECTION 0x0D +#define CMD_LOAD_RC_ID_TABLE 0x0E +#define CMD_LOAD_EC_ID_TABLE 0x0F + + +// *****************[ STK ISP command constants ]****************************** + +#define CMD_ENTER_PROGMODE_ISP 0x10 +#define CMD_LEAVE_PROGMODE_ISP 0x11 +#define CMD_CHIP_ERASE_ISP 0x12 +#define CMD_PROGRAM_FLASH_ISP 0x13 +#define CMD_READ_FLASH_ISP 0x14 +#define CMD_PROGRAM_EEPROM_ISP 0x15 +#define CMD_READ_EEPROM_ISP 0x16 +#define CMD_PROGRAM_FUSE_ISP 0x17 +#define CMD_READ_FUSE_ISP 0x18 +#define CMD_PROGRAM_LOCK_ISP 0x19 +#define CMD_READ_LOCK_ISP 0x1A +#define CMD_READ_SIGNATURE_ISP 0x1B +#define CMD_READ_OSCCAL_ISP 0x1C +#define CMD_SPI_MULTI 0x1D + +// *****************[ STK PP command constants ]******************************* + +#define CMD_ENTER_PROGMODE_PP 0x20 +#define CMD_LEAVE_PROGMODE_PP 0x21 +#define CMD_CHIP_ERASE_PP 0x22 +#define CMD_PROGRAM_FLASH_PP 0x23 +#define CMD_READ_FLASH_PP 0x24 +#define CMD_PROGRAM_EEPROM_PP 0x25 +#define CMD_READ_EEPROM_PP 0x26 +#define CMD_PROGRAM_FUSE_PP 0x27 +#define CMD_READ_FUSE_PP 0x28 +#define CMD_PROGRAM_LOCK_PP 0x29 +#define CMD_READ_LOCK_PP 0x2A +#define CMD_READ_SIGNATURE_PP 0x2B +#define CMD_READ_OSCCAL_PP 0x2C + +#define CMD_SET_CONTROL_STACK 0x2D + +// *****************[ STK HVSP command constants ]***************************** + +#define CMD_ENTER_PROGMODE_HVSP 0x30 +#define CMD_LEAVE_PROGMODE_HVSP 0x31 +#define CMD_CHIP_ERASE_HVSP 0x32 +#define CMD_PROGRAM_FLASH_HVSP 0x33 +#define CMD_READ_FLASH_HVSP 0x34 +#define CMD_PROGRAM_EEPROM_HVSP 0x35 +#define CMD_READ_EEPROM_HVSP 0x36 +#define CMD_PROGRAM_FUSE_HVSP 0x37 +#define CMD_READ_FUSE_HVSP 0x38 +#define CMD_PROGRAM_LOCK_HVSP 0x39 +#define CMD_READ_LOCK_HVSP 0x3A +#define CMD_READ_SIGNATURE_HVSP 0x3B +#define CMD_READ_OSCCAL_HVSP 0x3C +// These two are redefined since 0x30/0x31 collide +// with the STK600 bootloader. +#define CMD_ENTER_PROGMODE_HVSP_STK600 0x3D +#define CMD_LEAVE_PROGMODE_HVSP_STK600 0x3E + +// *** XPROG command constants *** + +#define CMD_XPROG 0x50 +#define CMD_XPROG_SETMODE 0x51 + + +// *** AVR32 JTAG Programming command *** + +#define CMD_JTAG_AVR32 0x80 +#define CMD_ENTER_PROGMODE_JTAG_AVR32 0x81 +#define CMD_LEAVE_PROGMODE_JTAG_AVR32 0x82 + + +// *** AVR JTAG Programming command *** + +#define CMD_JTAG_AVR 0x90 + +// *****************[ STK test command constants ]*************************** + +#define CMD_ENTER_TESTMODE 0x60 +#define CMD_LEAVE_TESTMODE 0x61 +#define CMD_CHIP_WRITE 0x62 +#define CMD_PROGRAM_FLASH_PARTIAL 0x63 +#define CMD_PROGRAM_EEPROM_PARTIAL 0x64 +#define CMD_PROGRAM_SIGNATURE_ROW 0x65 +#define CMD_READ_FLASH_MARGIN 0x66 +#define CMD_READ_EEPROM_MARGIN 0x67 +#define CMD_READ_SIGNATURE_ROW_MARGIN 0x68 +#define CMD_PROGRAM_TEST_FUSE 0x69 +#define CMD_READ_TEST_FUSE 0x6A +#define CMD_PROGRAM_HIDDEN_FUSE_LOW 0x6B +#define CMD_READ_HIDDEN_FUSE_LOW 0x6C +#define CMD_PROGRAM_HIDDEN_FUSE_HIGH 0x6D +#define CMD_READ_HIDDEN_FUSE_HIGH 0x6E +#define CMD_PROGRAM_HIDDEN_FUSE_EXT 0x6F +#define CMD_READ_HIDDEN_FUSE_EXT 0x70 + +// *****************[ STK status constants ]*************************** + +// Success +#define STATUS_CMD_OK 0x00 + +// Warnings +#define STATUS_CMD_TOUT 0x80 +#define STATUS_RDY_BSY_TOUT 0x81 +#define STATUS_SET_PARAM_MISSING 0x82 + +// Errors +#define STATUS_CMD_FAILED 0xC0 +#define STATUS_CKSUM_ERROR 0xC1 +#define STATUS_CMD_UNKNOWN 0xC9 +#define STATUS_CMD_ILLEGAL_PARAMETER 0xCA + +// Status +#define STATUS_ISP_READY 0x00 +#define STATUS_CONN_FAIL_MOSI 0x01 +#define STATUS_CONN_FAIL_RST 0x02 +#define STATUS_CONN_FAIL_SCK 0x04 +#define STATUS_TGT_NOT_DETECTED 0x10 +#define STATUS_TGT_REVERSE_INSERTED 0x20 + +// hw_status +// Bits in status variable +// Bit 0-3: Slave MCU +// Bit 4-7: Master MCU + +#define STATUS_AREF_ERROR 0 +// Set to '1' if AREF is short circuited + +#define STATUS_VTG_ERROR 4 +// Set to '1' if VTG is short circuited + +#define STATUS_RC_CARD_ERROR 5 +// Set to '1' if board id changes when board is powered + +#define STATUS_PROGMODE 6 +// Set to '1' if board is in programming mode + +#define STATUS_POWER_SURGE 7 +// Set to '1' if board draws excessive current + +// *****************[ STK parameter constants ]*************************** +#define PARAM_BUILD_NUMBER_LOW 0x80 /* ??? */ +#define PARAM_BUILD_NUMBER_HIGH 0x81 /* ??? */ +#define PARAM_HW_VER 0x90 +#define PARAM_SW_MAJOR 0x91 +#define PARAM_SW_MINOR 0x92 +#define PARAM_VTARGET 0x94 +#define PARAM_VADJUST 0x95 /* STK500 only */ +#define PARAM_OSC_PSCALE 0x96 /* STK500 only */ +#define PARAM_OSC_CMATCH 0x97 /* STK500 only */ +#define PARAM_SCK_DURATION 0x98 /* STK500 only */ +#define PARAM_TOPCARD_DETECT 0x9A /* STK500 only */ +#define PARAM_STATUS 0x9C /* STK500 only */ +#define PARAM_DATA 0x9D /* STK500 only */ +#define PARAM_RESET_POLARITY 0x9E /* STK500 only, and STK600 FW + * version <= 2.0.3 */ +#define PARAM_CONTROLLER_INIT 0x9F + +/* STK600 parameters */ +#define PARAM_STATUS_TGT_CONN 0xA1 +#define PARAM_DISCHARGEDELAY 0xA4 +#define PARAM_SOCKETCARD_ID 0xA5 +#define PARAM_ROUTINGCARD_ID 0xA6 +#define PARAM_EXPCARD_ID 0xA7 +#define PARAM_SW_MAJOR_SLAVE1 0xA8 +#define PARAM_SW_MINOR_SLAVE1 0xA9 +#define PARAM_SW_MAJOR_SLAVE2 0xAA +#define PARAM_SW_MINOR_SLAVE2 0xAB +#define PARAM_BOARD_ID_STATUS 0xAD +#define PARAM_RESET 0xB4 + +#define PARAM_JTAG_ALLOW_FULL_PAGE_STREAM 0x50 +#define PARAM_JTAG_EEPROM_PAGE_SIZE 0x52 +#define PARAM_JTAG_DAISY_BITS_BEFORE 0x53 +#define PARAM_JTAG_DAISY_BITS_AFTER 0x54 +#define PARAM_JTAG_DAISY_UNITS_BEFORE 0x55 +#define PARAM_JTAG_DAISY_UNITS_AFTER 0x56 + +// *** Parameter constants for 2 byte values *** +#define PARAM2_SCK_DURATION 0xC0 +#define PARAM2_CLOCK_CONF 0xC1 +#define PARAM2_AREF0 0xC2 +#define PARAM2_AREF1 0xC3 + +#define PARAM2_JTAG_FLASH_SIZE_H 0xC5 +#define PARAM2_JTAG_FLASH_SIZE_L 0xC6 +#define PARAM2_JTAG_FLASH_PAGE_SIZE 0xC7 +#define PARAM2_RC_ID_TABLE_REV 0xC8 +#define PARAM2_EC_ID_TABLE_REV 0xC9 + +/* STK600 XPROG section */ +// XPROG modes +#define XPRG_MODE_PDI 0 +#define XPRG_MODE_JTAG 1 +#define XPRG_MODE_TPI 2 + +// XPROG commands +#define XPRG_CMD_ENTER_PROGMODE 0x01 +#define XPRG_CMD_LEAVE_PROGMODE 0x02 +#define XPRG_CMD_ERASE 0x03 +#define XPRG_CMD_WRITE_MEM 0x04 +#define XPRG_CMD_READ_MEM 0x05 +#define XPRG_CMD_CRC 0x06 +#define XPRG_CMD_SET_PARAM 0x07 + +// Memory types +#define XPRG_MEM_TYPE_APPL 1 +#define XPRG_MEM_TYPE_BOOT 2 +#define XPRG_MEM_TYPE_EEPROM 3 +#define XPRG_MEM_TYPE_FUSE 4 +#define XPRG_MEM_TYPE_LOCKBITS 5 +#define XPRG_MEM_TYPE_USERSIG 6 +#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7 + +// Erase types +#define XPRG_ERASE_CHIP 1 +#define XPRG_ERASE_APP 2 +#define XPRG_ERASE_BOOT 3 +#define XPRG_ERASE_EEPROM 4 +#define XPRG_ERASE_APP_PAGE 5 +#define XPRG_ERASE_BOOT_PAGE 6 +#define XPRG_ERASE_EEPROM_PAGE 7 +#define XPRG_ERASE_USERSIG 8 +#define XPRG_ERASE_CONFIG 9 // TPI only, prepare fuse write + +// Write mode flags +#define XPRG_MEM_WRITE_ERASE 0 +#define XPRG_MEM_WRITE_WRITE 1 + +// CRC types +#define XPRG_CRC_APP 1 +#define XPRG_CRC_BOOT 2 +#define XPRG_CRC_FLASH 3 + +// Error codes +#define XPRG_ERR_OK 0 +#define XPRG_ERR_FAILED 1 +#define XPRG_ERR_COLLISION 2 +#define XPRG_ERR_TIMEOUT 3 + +// XPROG parameters of different sizes +// 4-byte address +#define XPRG_PARAM_NVMBASE 0x01 +// 2-byte page size +#define XPRG_PARAM_EEPPAGESIZE 0x02 +// 1-byte, undocumented TPI param +#define XPRG_PARAM_TPI_3 0x03 +// 1-byte, undocumented TPI param +#define XPRG_PARAM_TPI_4 0x04 + +// *****************[ STK answer constants ]*************************** + +#define ANSWER_CKSUM_ERROR 0xB0 + +/* + * Private data for this programmer. + */ +struct pdata +{ + /* + * See stk500pp_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ + unsigned char *flash_pagecache; + unsigned long flash_pageaddr; + unsigned int flash_pagesize; + + unsigned char *eeprom_pagecache; + unsigned long eeprom_pageaddr; + unsigned int eeprom_pagesize; + + unsigned char command_sequence; + + enum + { + PGMTYPE_UNKNOWN, + PGMTYPE_STK500, + PGMTYPE_AVRISP, + PGMTYPE_AVRISP_MKII, + PGMTYPE_JTAGICE_MKII, + PGMTYPE_STK600, + } + pgmtype; + + AVRPART *lastpart; + + /* + * Chained pdata for the JTAG ICE mkII backend. This is used when + * calling the backend functions for ISP/HVSP/PP programming + * functionality of the JTAG ICE mkII and AVR Dragon. + */ + void *chained_pdata; +}; + diff --git a/avrdude/term.c b/avrdude/term.c new file mode 100644 index 00000000..a2448f4e --- /dev/null +++ b/avrdude/term.c @@ -0,0 +1,940 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include + +#if defined(HAVE_LIBREADLINE) +#if !defined(WIN32NATIVE) +# include +# include +#endif +#endif + +#include "avrdude.h" +#include "avr.h" +#include "config.h" +#include "lists.h" +#include "pgm.h" +#include "pindefs.h" +#include "ppi.h" + +struct command { + char * name; + int (*func)(PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); + char * desc; +}; + + +static int cmd_dump (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_write (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_erase (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_sig (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_part (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_help (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_quit (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_send (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_parms (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_vtarg (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_varef (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_sck (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_spi (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_pgm (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +struct command cmd[] = { + { "dump", cmd_dump, "dump memory : %s " }, + { "read", cmd_dump, "alias for dump" }, + { "write", cmd_write, "write memory : %s ... " }, + { "erase", cmd_erase, "perform a chip erase" }, + { "sig", cmd_sig, "display device signature bytes" }, + { "part", cmd_part, "display the current part information" }, + { "send", cmd_send, "send a raw command : %s " }, + { "parms", cmd_parms, "display adjustable parameters (STK500 only)" }, + { "vtarg", cmd_vtarg, "set (STK500 only)" }, + { "varef", cmd_varef, "set (STK500 only)" }, + { "fosc", cmd_fosc, "set (STK500 only)" }, + { "sck", cmd_sck, "set (STK500 only)" }, + { "spi", cmd_spi, "enter direct SPI mode" }, + { "pgm", cmd_pgm, "return to programming mode" }, + { "help", cmd_help, "help" }, + { "?", cmd_help, "help" }, + { "quit", cmd_quit, "quit" } +}; + +#define NCMDS (sizeof(cmd)/sizeof(struct command)) + + + +static int spi_mode = 0; + +static int nexttok(char * buf, char ** tok, char ** next) +{ + char * q, * n; + + q = buf; + while (isspace((int)*q)) + q++; + + /* isolate first token */ + n = q+1; + while (*n && !isspace((int)*n)) + n++; + + if (*n) { + *n = 0; + n++; + } + + /* find start of next token */ + while (isspace((int)*n)) + n++; + + *tok = q; + *next = n; + + return 0; +} + + +static int hexdump_line(char * buffer, unsigned char * p, int n, int pad) +{ + char * hexdata = "0123456789abcdef"; + char * b; + int i, j; + + b = buffer; + + j = 0; + for (i=0; i> 4]; + b[j++] = hexdata[(p[i] & 0x0f)]; + if (i < 15) + b[j++] = ' '; + } + + for (i=j; i len) + n = len; + hexdump_line(dst1, p, n, 48); + chardump_line(dst2, p, n, 16); + fprintf(stdout, "%04x %s |%s|\n", addr, dst1, dst2); + len -= n; + addr += n; + p += n; + } + + return 0; +} + + +static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + static char prevmem[128] = {0}; + char * e; + unsigned char * buf; + int maxsize; + unsigned long i; + static unsigned long addr=0; + static int len=64; + AVRMEM * mem; + char * memtype = NULL; + int rc; + + if (!((argc == 2) || (argc == 4))) { + fprintf(stderr, "Usage: dump [ ]\n"); + return -1; + } + + memtype = argv[1]; + + if (strncmp(prevmem, memtype, strlen(memtype)) != 0) { + addr = 0; + len = 64; + strncpy(prevmem, memtype, sizeof(prevmem)-1); + prevmem[sizeof(prevmem)-1] = 0; + } + + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", + memtype, p->desc); + return -1; + } + + if (argc == 4) { + addr = strtoul(argv[2], &e, 0); + if (*e || (e == argv[2])) { + fprintf(stderr, "%s (dump): can't parse address \"%s\"\n", + progname, argv[2]); + return -1; + } + + len = strtol(argv[3], &e, 0); + if (*e || (e == argv[3])) { + fprintf(stderr, "%s (dump): can't parse length \"%s\"\n", + progname, argv[3]); + return -1; + } + } + + maxsize = mem->size; + + if (addr >= maxsize) { + if (argc == 2) { + /* wrap around */ + addr = 0; + } + else { + fprintf(stderr, + "%s (dump): address 0x%05lx is out of range for %s memory\n", + progname, addr, mem->desc); + return -1; + } + } + + /* trim len if nessary to not read past the end of memory */ + if ((addr + len) > maxsize) + len = maxsize - addr; + + buf = malloc(len); + if (buf == NULL) { + fprintf(stderr, "%s (dump): out of memory\n", progname); + return -1; + } + + for (i=0; iread_byte(pgm, p, mem, addr+i, &buf[i]); + if (rc != 0) { + fprintf(stderr, "error reading %s address 0x%05lx of part %s\n", + mem->desc, addr+i, p->desc); + if (rc == -1) + fprintf(stderr, "read operation not supported on memory type \"%s\"\n", + mem->desc); + return -1; + } + } + + hexdump_buf(stdout, addr, buf, len); + + fprintf(stdout, "\n"); + + free(buf); + + addr = addr + len; + + return 0; +} + + +static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + char * e; + int len, maxsize; + char * memtype; + unsigned long addr, i; + unsigned char * buf; + unsigned char b; + int rc; + int werror; + AVRMEM * mem; + + if (argc < 4) { + fprintf(stderr, "Usage: write " + " ... byteN>\n"); + return -1; + } + + memtype = argv[1]; + + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", + memtype, p->desc); + return -1; + } + + maxsize = mem->size; + + addr = strtoul(argv[2], &e, 0); + if (*e || (e == argv[2])) { + fprintf(stderr, "%s (write): can't parse address \"%s\"\n", + progname, argv[2]); + return -1; + } + + if (addr > maxsize) { + fprintf(stderr, + "%s (write): address 0x%05lx is out of range for %s memory\n", + progname, addr, memtype); + return -1; + } + + /* number of bytes to write at the specified address */ + len = argc - 3; + + if ((addr + len) > maxsize) { + fprintf(stderr, + "%s (write): selected address and # bytes exceed " + "range for %s memory\n", + progname, memtype); + return -1; + } + + buf = malloc(len); + if (buf == NULL) { + fprintf(stderr, "%s (write): out of memory\n", progname); + return -1; + } + + for (i=3; ierr_led(pgm, OFF); + for (werror=0, i=0; idesc); + werror = 1; + } + + rc = pgm->read_byte(pgm, p, mem, addr+i, &b); + if (b != buf[i]) { + fprintf(stderr, + "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n", + progname, buf[i], addr+i, b); + werror = 1; + } + + if (werror) { + pgm->err_led(pgm, ON); + } + } + + free(buf); + + fprintf(stdout, "\n"); + + return 0; +} + + +static int cmd_send(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + unsigned char cmd[4], res[4]; + char * e; + int i; + int len; + + if (pgm->cmd == NULL) { + fprintf(stderr, + "The %s programmer does not support direct ISP commands.\n", + pgm->type); + return -1; + } + + if (spi_mode && (pgm->spi == NULL)) { + fprintf(stderr, + "The %s programmer does not support direct SPI transfers.\n", + pgm->type); + return -1; + } + + + if ((argc > 5) || ((argc < 5) && (!spi_mode))) { + fprintf(stderr, spi_mode? + "Usage: send [ [ []]]\n": + "Usage: send \n"); + return -1; + } + + /* number of bytes to write at the specified address */ + len = argc - 1; + + /* load command bytes */ + for (i=1; ierr_led(pgm, OFF); + + if (spi_mode) + pgm->spi(pgm, cmd, res, argc-1); + else + pgm->cmd(pgm, cmd, res); + + /* + * display results + */ + fprintf(stderr, "results:"); + for (i=0; ichip_erase(pgm, p); + return 0; +} + + +static int cmd_part(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + fprintf(stdout, "\n"); + avr_display(stdout, p, "", 0); + fprintf(stdout, "\n"); + + return 0; +} + + +static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + int i; + int rc; + AVRMEM * m; + + rc = avr_signature(pgm, p); + if (rc != 0) { + fprintf(stderr, "error reading signature data, rc=%d\n", + rc); + } + + m = avr_locate_mem(p, "signature"); + if (m == NULL) { + fprintf(stderr, + "signature data not defined for device \"%s\"\n", + p->desc); + } + else { + fprintf(stdout, "Device signature = 0x"); + for (i=0; isize; i++) + fprintf(stdout, "%02x", m->buf[i]); + fprintf(stdout, "\n\n"); + } + + return 0; +} + + +static int cmd_quit(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + return 1; +} + + +static int cmd_parms(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + if (pgm->print_parms == NULL) { + fprintf(stderr, + "%s (parms): the %s programmer does not support " + "adjustable parameters\n", + progname, pgm->type); + return -1; + } + pgm->print_parms(pgm); + + return 0; +} + + +static int cmd_vtarg(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + int rc; + double v; + char *endp; + + if (argc != 2) { + fprintf(stderr, "Usage: vtarg \n"); + return -1; + } + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + fprintf(stderr, "%s (vtarg): can't parse voltage \"%s\"\n", + progname, argv[1]); + return -1; + } + if (pgm->set_vtarget == NULL) { + fprintf(stderr, "%s (vtarg): the %s programmer cannot set V[target]\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_vtarget(pgm, v)) != 0) { + fprintf(stderr, "%s (vtarg): failed to set V[target] (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + +static int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + int rc; + double v; + char *endp; + + if (argc != 2) { + fprintf(stderr, "Usage: fosc [M|k] | off\n"); + return -1; + } + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + if (strcmp(argv[1], "off") == 0) + v = 0.0; + else { + fprintf(stderr, "%s (fosc): can't parse frequency \"%s\"\n", + progname, argv[1]); + return -1; + } + } + if (*endp == 'm' || *endp == 'M') + v *= 1e6; + else if (*endp == 'k' || *endp == 'K') + v *= 1e3; + if (pgm->set_fosc == NULL) { + fprintf(stderr, + "%s (fosc): the %s programmer cannot set oscillator frequency\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_fosc(pgm, v)) != 0) { + fprintf(stderr, "%s (fosc): failed to set oscillator_frequency (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + +static int cmd_sck(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + int rc; + double v; + char *endp; + + if (argc != 2) { + fprintf(stderr, "Usage: sck \n"); + return -1; + } + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + fprintf(stderr, "%s (sck): can't parse period \"%s\"\n", + progname, argv[1]); + return -1; + } + v *= 1e-6; /* Convert from microseconds to seconds. */ + if (pgm->set_sck_period == NULL) { + fprintf(stderr, + "%s (sck): the %s programmer cannot set SCK period\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_sck_period(pgm, v)) != 0) { + fprintf(stderr, "%s (sck): failed to set SCK period (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + +static int cmd_varef(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + int rc; + unsigned int chan; + double v; + char *endp; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage: varef [channel] \n"); + return -1; + } + if (argc == 2) { + chan = 0; + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + fprintf(stderr, "%s (varef): can't parse voltage \"%s\"\n", + progname, argv[1]); + return -1; + } + } else { + chan = strtoul(argv[1], &endp, 10); + if (endp == argv[1]) { + fprintf(stderr, "%s (varef): can't parse channel \"%s\"\n", + progname, argv[1]); + return -1; + } + v = strtod(argv[2], &endp); + if (endp == argv[2]) { + fprintf(stderr, "%s (varef): can't parse voltage \"%s\"\n", + progname, argv[2]); + return -1; + } + } + if (pgm->set_varef == NULL) { + fprintf(stderr, "%s (varef): the %s programmer cannot set V[aref]\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_varef(pgm, chan, v)) != 0) { + fprintf(stderr, "%s (varef): failed to set V[aref] (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + +static int cmd_help(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + int i; + + fprintf(stdout, "Valid commands:\n\n"); + for (i=0; isetpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); + spi_mode = 1; + return 0; +} + +static int cmd_pgm(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0); + spi_mode = 0; + pgm->initialize(pgm, p); + return 0; +} + +static int tokenize(char * s, char *** argv) +{ + int i, n, l, nargs, offset; + int len, slen; + char * buf; + int bufsize; + char ** bufv; + char * q, * r; + char * nbuf; + char ** av; + + slen = strlen(s); + + /* + * initialize allow for 20 arguments, use realloc to grow this if + * necessary + */ + nargs = 20; + bufsize = slen + 20; + buf = malloc(bufsize); + bufv = (char **) malloc(nargs*sizeof(char *)); + for (i=0; i= 1)) + add_history(input); + + return input; +#else + char input[256]; + printf("%s", prompt); + if (fgets(input, sizeof(input), stdin)) + { + /* FIXME: readline strips the '\n', should this too? */ + return strdup(input); + } + else + return NULL; +#endif +} + + +int terminal_mode(PROGRAMMER * pgm, struct avrpart * p) +{ + char * cmdbuf; + int i; + char * q; + int rc; + int argc; + char ** argv; + + rc = 0; + while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) { + /* + * find the start of the command, skipping any white space + */ + q = cmdbuf; + while (*q && isspace((int)*q)) + q++; + + /* skip blank lines and comments */ + if (!*q || (*q == '#')) + continue; + + /* tokenize command line */ + argc = tokenize(q, &argv); + + fprintf(stdout, ">>> "); + for (i=0; i 0) { + rc = 0; + break; + } + free(cmdbuf); + } + + return rc; +} + + diff --git a/avrdude/term.h b/avrdude/term.h new file mode 100644 index 00000000..42d8a7a2 --- /dev/null +++ b/avrdude/term.h @@ -0,0 +1,39 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef term_h +#define term_h + +#include "avr.h" +#include "pgm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); +char * terminal_get_input(const char *prompt); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/tools/get-dw-params.xsl b/avrdude/tools/get-dw-params.xsl new file mode 100644 index 00000000..457617bc --- /dev/null +++ b/avrdude/tools/get-dw-params.xsl @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + #------------------------------------------------------------ + # + + + #------------------------------------------------------------ + part desc = " + + "; has_debugwire = yes; + + flash_instr = + + + + + ; + + eeprom_instr = + + + + + ; + + + + + + + + + + + + + 0 + + + + + + + + + + + 0 + + + 0x + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + , + + + + + + + + + + + + + + + + + + + + + + diff --git a/avrdude/tools/get-hv-params.xsl b/avrdude/tools/get-hv-params.xsl new file mode 100644 index 00000000..f86bd2b0 --- /dev/null +++ b/avrdude/tools/get-hv-params.xsl @@ -0,0 +1,255 @@ + + + + + + + + + + + + pp_controlstack = + + + + ; + + + + + hventerstabdelay = ; + + progmodedelay = ; + + latchcycles = ; + + togglevtg = ; + + poweroffdelay = ; + + resetdelayms = ; + + resetdelayus = ; + + + + + + + hvleavestabdelay = ; + + + + + + + chiperasepulsewidth = ; + + chiperasepolltimeout = ; + + + + + + + programfusepulsewidth = ; + + programfusepolltimeout = ; + + + + + + + programlockpulsewidth = ; + + programlockpolltimeout = ; + + + + + + + + + + hvsp_controlstack = + + + + ; + + + + + hventerstabdelay = ; + + hvspcmdexedelay = ; + + synchcycles = ; + + latchcycles = ; + + togglevtg = ; + + poweroffdelay = ; + + resetdelayms = ; + + resetdelayus = ; + + + + + + + hvleavestabdelay = ; + + resetdelay = ; + + + + + + + chiperasepolltimeout = ; + + chiperasetime = ; + + + + + + + programfusepolltimeout = ; + + + + + + + programlockpolltimeout = ; + + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + , + + + + + + + + + + diff --git a/avrdude/tools/get-stk600-cards.xsl b/avrdude/tools/get-stk600-cards.xsl new file mode 100644 index 00000000..c71d5147 --- /dev/null +++ b/avrdude/tools/get-stk600-cards.xsl @@ -0,0 +1,63 @@ + + + + + + + + + + { + + , " + + " }, + + + + + + + + { + + , " + + " }, + + + + + + diff --git a/avrdude/tools/get-stk600-devices.xsl b/avrdude/tools/get-stk600-devices.xsl new file mode 100644 index 00000000..241994b9 --- /dev/null +++ b/avrdude/tools/get-stk600-devices.xsl @@ -0,0 +1,52 @@ + + + + + + + @multitable @columnfractions .15 .15 .6 + Routing card @tab Socket card @tab Devices + + @item @code{ + + } @tab @code{ + + } @tab + + + + + + + @end multitable + + + diff --git a/avrdude/tpi.h b/avrdude/tpi.h new file mode 100644 index 00000000..e99d091a --- /dev/null +++ b/avrdude/tpi.h @@ -0,0 +1,72 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2011 Darell Tan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef tpi_h +#define tpi_h + +#ifdef __cplusplus +extern "C" { +#endif + +static const unsigned char tpi_skey[] = { 0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF }; + +/* registers */ +#define TPI_REG_TPIIR 0x0F +#define TPI_REG_TPIPCR 0x02 +#define TPI_REG_TPISR 0x00 + +#define TPI_REG_TPISR_NVMEN (1 << 1) + +/* TPI commands */ +#define TPI_CMD_SLD 0x20 +#define TPI_CMD_SLD_PI 0x24 +#define TPI_CMD_SIN 0x10 +#define TPI_CMD_SOUT 0x90 +#define TPI_CMD_SSTCS 0xC0 +#define TPI_CMD_SST 0x60 +#define TPI_CMD_SST_PI 0x64 + +#define TPI_CMD_SLDCS 0x80 +#define TPI_CMD_SSTPR 0x68 +#define TPI_CMD_SKEY 0xE0 + +/* for TPI_CMD_SIN & TPI_CMD_SOUT */ +#define TPI_SIO_ADDR(x) ((x & 0x30) << 1 | (x & 0x0F)) + +/* ATtiny4/5/9/10 I/O registers */ +#define TPI_IOREG_NVMCSR 0x32 +#define TPI_IOREG_NVMCMD 0x33 + +/* bit for NVMCSR */ +#define TPI_IOREG_NVMCSR_NVMBSY (1 << 7) + +/* NVM commands */ +#define TPI_NVMCMD_NO_OPERATION 0x00 +#define TPI_NVMCMD_CHIP_ERASE 0x10 +#define TPI_NVMCMD_SECTION_ERASE 0x14 +#define TPI_NVMCMD_WORD_WRITE 0x1D + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/avrdude/update.c b/avrdude/update.c new file mode 100644 index 00000000..4350eb8c --- /dev/null +++ b/avrdude/update.c @@ -0,0 +1,372 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2005 Brian S. Dean + * Copyright (C) 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "config.h" +#include "confwin.h" +#include "fileio.h" +#include "update.h" + +UPDATE * parse_op(char * s) +{ + char buf[1024]; + char * p, * cp, c; + UPDATE * upd; + int i; + size_t fnlen; + + upd = (UPDATE *)malloc(sizeof(UPDATE)); + if (upd == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + + i = 0; + p = s; + while ((i < (sizeof(buf)-1) && *p && (*p != ':'))) + buf[i++] = *p++; + buf[i] = 0; + + if (*p != ':') { + upd->memtype = (char *)malloc(strlen("flash")+1); + if (upd->memtype == NULL) { + outofmem: + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + strcpy(upd->memtype, "flash"); + upd->op = DEVICE_WRITE; + upd->filename = (char *)malloc(strlen(buf) + 1); + if (upd->filename == NULL) + goto outofmem; + strcpy(upd->filename, buf); + upd->format = FMT_AUTO; + return upd; + } + + upd->memtype = (char *)malloc(strlen(buf)+1); + if (upd->memtype == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + strcpy(upd->memtype, buf); + + p++; + if (*p == 'r') { + upd->op = DEVICE_READ; + } + else if (*p == 'w') { + upd->op = DEVICE_WRITE; + } + else if (*p == 'v') { + upd->op = DEVICE_VERIFY; + } + else { + fprintf(stderr, "%s: invalid I/O mode '%c' in update specification\n", + progname, *p); + fprintf(stderr, + " allowed values are:\n" + " r = read device\n" + " w = write device\n" + " v = verify device\n"); + free(upd->memtype); + free(upd); + return NULL; + } + + p++; + + if (*p != ':') { + fprintf(stderr, "%s: invalid update specification\n", progname); + free(upd->memtype); + free(upd); + return NULL; + } + + p++; + + /* + * Now, parse the filename component. Instead of looking for the + * leftmost possible colon delimiter, we look for the rightmost one. + * If we found one, we do have a trailing :format specifier, and + * process it. Otherwise, the remainder of the string is our file + * name component. That way, the file name itself is allowed to + * contain a colon itself (e. g. C:/some/file.hex), except the + * optional format specifier becomes mandatory then. + */ + cp = p; + p = strrchr(cp, ':'); + if (p == NULL) { + upd->format = FMT_AUTO; + fnlen = strlen(cp); + upd->filename = (char *)malloc(fnlen + 1); + } else { + fnlen = p - cp; + upd->filename = (char *)malloc(fnlen +1); + c = *++p; + if (c && p[1]) + /* More than one char - force failure below. */ + c = '?'; + switch (c) { + case 'a': upd->format = FMT_AUTO; break; + case 's': upd->format = FMT_SREC; break; + case 'i': upd->format = FMT_IHEX; break; + case 'r': upd->format = FMT_RBIN; break; + case 'm': upd->format = FMT_IMM; break; + case 'b': upd->format = FMT_BIN; break; + case 'd': upd->format = FMT_DEC; break; + case 'h': upd->format = FMT_HEX; break; + case 'o': upd->format = FMT_OCT; break; + default: + fprintf(stderr, "%s: invalid file format '%s' in update specifier\n", + progname, p); + free(upd->memtype); + free(upd); + return NULL; + } + } + + if (upd->filename == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + free(upd->memtype); + free(upd); + return NULL; + } + memcpy(upd->filename, cp, fnlen); + upd->filename[fnlen] = 0; + + return upd; +} + +UPDATE * dup_update(UPDATE * upd) +{ + UPDATE * u; + + u = (UPDATE *)malloc(sizeof(UPDATE)); + if (u == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + + memcpy(u, upd, sizeof(UPDATE)); + + u->memtype = strdup(upd->memtype); + u->filename = strdup(upd->filename); + + return u; +} + +UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) +{ + UPDATE * u; + + u = (UPDATE *)malloc(sizeof(UPDATE)); + if (u == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + + u->memtype = strdup(memtype); + u->filename = strdup(filename); + u->op = op; + u->format = filefmt; + + return u; +} + +int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite, + int verify) +{ + struct avrpart * v; + AVRMEM * mem; + int size, vsize; + int rc; + + mem = avr_locate_mem(p, upd->memtype); + if (mem == NULL) { + fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", + upd->memtype, p->desc); + return -1; + } + + if (upd->op == DEVICE_READ) { + /* + * read out the specified device memory and write it to a file + */ + if (quell_progress < 2) { + fprintf(stderr, "%s: reading %s memory:\n", + progname, mem->desc); + } + report_progress(0,1,"Reading"); + rc = avr_read(pgm, p, upd->memtype, 0, 1); + if (rc < 0) { + fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", + progname, mem->desc, rc); + return -1; + } + report_progress(1,1,NULL); + size = rc; + + if (quell_progress < 2) { + fprintf(stderr, + "%s: writing output file \"%s\"\n", + progname, + strcmp(upd->filename, "-")==0 ? "" : upd->filename); + } + rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size); + if (rc < 0) { + fprintf(stderr, "%s: write to file '%s' failed\n", + progname, upd->filename); + return -1; + } + } + else if (upd->op == DEVICE_WRITE) { + /* + * write the selected device memory using data from a file; first + * read the data from the specified file + */ + if (quell_progress < 2) { + fprintf(stderr, + "%s: reading input file \"%s\"\n", + progname, + strcmp(upd->filename, "-")==0 ? "" : upd->filename); + } + rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); + if (rc < 0) { + fprintf(stderr, "%s: read from file '%s' failed\n", + progname, upd->filename); + return -1; + } + size = rc; + + /* + * write the buffer contents to the selected memory type + */ + if (quell_progress < 2) { + fprintf(stderr, "%s: writing %s (%d bytes):\n", + progname, mem->desc, size); + } + + if (!nowrite) { + report_progress(0,1,"Writing"); + rc = avr_write(pgm, p, upd->memtype, size, 1); + report_progress(1,1,NULL); + } + else { + /* + * test mode, don't actually write to the chip, output the buffer + * to stdout in intel hex instead + */ + rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size); + } + + if (rc < 0) { + fprintf(stderr, "%s: failed to write %s memory, rc=%d\n", + progname, mem->desc, rc); + return -1; + } + + vsize = rc; + + if (quell_progress < 2) { + fprintf(stderr, "%s: %d bytes of %s written\n", progname, + vsize, mem->desc); + } + + } + else if (upd->op == DEVICE_VERIFY) { + /* + * verify that the in memory file (p->mem[AVR_M_FLASH|AVR_M_EEPROM]) + * is the same as what is on the chip + */ + pgm->vfy_led(pgm, ON); + + v = avr_dup_part(p); + + if (quell_progress < 2) { + fprintf(stderr, "%s: verifying %s memory against %s:\n", + progname, mem->desc, upd->filename); + + fprintf(stderr, "%s: load data %s data from input file %s:\n", + progname, mem->desc, upd->filename); + } + + rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); + if (rc < 0) { + fprintf(stderr, "%s: read from file '%s' failed\n", + progname, upd->filename); + return -1; + } + size = rc; + if (quell_progress < 2) { + fprintf(stderr, "%s: input file %s contains %d bytes\n", + progname, upd->filename, size); + fprintf(stderr, "%s: reading on-chip %s data:\n", + progname, mem->desc); + } + + report_progress (0,1,"Reading"); + rc = avr_read(pgm, v, upd->memtype, size, 1); + if (rc < 0) { + fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", + progname, mem->desc, rc); + pgm->err_led(pgm, ON); + return -1; + } + report_progress (1,1,NULL); + + + + if (quell_progress < 2) { + fprintf(stderr, "%s: verifying ...\n", progname); + } + rc = avr_verify(p, v, upd->memtype, size); + if (rc < 0) { + fprintf(stderr, "%s: verification error; content mismatch\n", + progname); + pgm->err_led(pgm, ON); + return -1; + } + + if (quell_progress < 2) { + fprintf(stderr, "%s: %d bytes of %s verified\n", + progname, rc, mem->desc); + } + + pgm->vfy_led(pgm, OFF); + } + else { + fprintf(stderr, "%s: invalid update operation (%d) requested\n", + progname, upd->op); + return -1; + } + + return 0; +} + diff --git a/avrdude/update.h b/avrdude/update.h new file mode 100644 index 00000000..32e445d4 --- /dev/null +++ b/avrdude/update.h @@ -0,0 +1,55 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2005 Brian S. Dean + * Copyright (C) 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef update_h +#define update_h + +enum { + DEVICE_READ, + DEVICE_WRITE, + DEVICE_VERIFY +}; + + +typedef struct update_t { + char * memtype; + int op; + char * filename; + int format; +} UPDATE; + +#ifdef __cplusplus +extern "C" { +#endif + +extern UPDATE * parse_op(char * s); +extern UPDATE * dup_update(UPDATE * upd); +extern UPDATE * new_update(int op, char * memtype, int filefmt, + char * filename); +extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, + int nowrite, int verify); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/avrdude/usb_libusb.c b/avrdude/usb_libusb.c new file mode 100644 index 00000000..cc476a6d --- /dev/null +++ b/avrdude/usb_libusb.c @@ -0,0 +1,483 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005,2006 Joerg Wunsch + * Copyright (C) 2006 David Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * USB interface via libusb for avrdude. + */ + +#include "ac_cfg.h" +#if defined(HAVE_LIBUSB) + + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "avrdude.h" +#include "serial.h" +#include "usbdevs.h" + +#if defined(WIN32NATIVE) +/* someone has defined "interface" to "struct" in Cygwin */ +# undef interface +#endif + +static char usbbuf[USBDEV_MAX_XFER]; +static int buflen = -1, bufptr; + +static int usb_interface; + +/* + * The "baud" parameter is meaningless for USB devices, so we reuse it + * to pass the desired USB device ID. + */ +static int usbdev_open(char * port, long baud, union filedescriptor *fd) +{ + char string[256]; + char product[256]; + struct usb_bus *bus; + struct usb_device *dev; + usb_dev_handle *udev; + char *serno, *cp2; + int i; + size_t x; + + /* + * The syntax for usb devices is defined as: + * + * -P usb[:serialnumber] + * + * See if we've got a serial number passed here. The serial number + * might contain colons which we remove below, and we compare it + * right-to-left, so only the least significant nibbles need to be + * specified. + */ + if ((serno = strchr(port, ':')) != NULL) + { + /* first, drop all colons there if any */ + cp2 = ++serno; + + while ((cp2 = strchr(cp2, ':')) != NULL) + { + x = strlen(cp2) - 1; + memmove(cp2, cp2 + 1, x); + cp2[x] = '\0'; + } + + if (strlen(serno) > 12) + { + fprintf(stderr, + "%s: usbdev_open(): invalid serial number \"%s\"\n", + progname, serno); + exit(1); + } + } + + usb_init(); + + usb_find_busses(); + usb_find_devices(); + + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + udev = usb_open(dev); + if (udev) + { + if (dev->descriptor.idVendor == USB_VENDOR_ATMEL && + dev->descriptor.idProduct == (unsigned short)baud) + { + /* yeah, we found something */ + if (usb_get_string_simple(udev, + dev->descriptor.iSerialNumber, + string, sizeof(string)) < 0) + { + fprintf(stderr, + "%s: usb_open(): cannot read serial number \"%s\"\n", + progname, usb_strerror()); + /* + * On some systems, libusb appears to have + * problems sending control messages. Catch the + * benign case where the user did not request a + * particular serial number, so we could + * continue anyway. + */ + if (serno != NULL) + exit(1); /* no chance */ + else + strcpy(string, "[unknown]"); + } + + if (usb_get_string_simple(udev, + dev->descriptor.iProduct, + product, sizeof(product)) < 0) + { + fprintf(stderr, + "%s: usb_open(): cannot read product name \"%s\"\n", + progname, usb_strerror()); + strcpy(product, "[unnamed product]"); + } + + if (verbose) + fprintf(stderr, + "%s: usbdev_open(): Found %s, serno: %s\n", + progname, product, string); + if (serno != NULL) + { + /* + * See if the serial number requested by the + * user matches what we found, matching + * right-to-left. + */ + x = strlen(string) - strlen(serno); + if (strcasecmp(string + x, serno) != 0) + { + if (verbose > 2) + fprintf(stderr, + "%s: usbdev_open(): serial number doesn't match\n", + progname); + usb_close(udev); + continue; + } + } + + if (dev->config == NULL) + { + fprintf(stderr, + "%s: usbdev_open(): USB device has no configuration\n", + progname); + goto trynext; + } + + if (usb_set_configuration(udev, dev->config[0].bConfigurationValue)) + { + fprintf(stderr, + "%s: usbdev_open(): error setting configuration %d: %s\n", + progname, dev->config[0].bConfigurationValue, + usb_strerror()); + goto trynext; + } + + usb_interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber; + if (usb_claim_interface(udev, usb_interface)) + { + fprintf(stderr, + "%s: usbdev_open(): error claiming interface %d: %s\n", + progname, usb_interface, usb_strerror()); + goto trynext; + } + + fd->usb.handle = udev; + fd->usb.ep = -1; + /* Try finding out what our read endpoint is. */ + for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++) + { + int possible_ep = dev->config[0].interface[0].altsetting[0]. + endpoint[i].bEndpointAddress; + + if ((possible_ep & USB_ENDPOINT_DIR_MASK) != 0) + { + if (verbose > 1) + { + fprintf(stderr, + "%s: usbdev_open(): using read endpoint 0x%02x\n", + progname, possible_ep); + } + fd->usb.ep = possible_ep; + break; + } + } + if (fd->usb.ep == -1) + { + fprintf(stderr, + "%s: usbdev_open(): cannot find a read endpoint, using 0x%02x\n", + progname, USBDEV_BULK_EP_READ); + fd->usb.ep = USBDEV_BULK_EP_READ; + } + return 0; + } + trynext: + usb_close(udev); + } + } + } + + fprintf(stderr, "%s: usbdev_open(): did not find any%s USB device \"%s\"\n", + progname, serno? " (matching)": "", port); + exit(1); +} + +static void usbdev_close(union filedescriptor *fd) +{ + usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle; + + (void)usb_release_interface(udev, usb_interface); + +#if !( defined(__FreeBSD__) ) // || ( defined(__APPLE__) && defined(__MACH__) ) ) + /* + * Without this reset, the AVRISP mkII seems to stall the second + * time we try to connect to it. This is not necessary on + * FreeBSD. + */ + usb_reset(udev); +#endif + + usb_close(udev); +} + + +static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen) +{ + usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle; + int rv; + int i = mlen; + unsigned char * p = bp; + int tx_size; + + /* + * Split the frame into multiple packets. It's important to make + * sure we finish with a short packet, or else the device won't know + * the frame is finished. For example, if we need to send 64 bytes, + * we must send a packet of length 64 followed by a packet of length + * 0. + */ + do { + tx_size = (mlen < USBDEV_MAX_XFER)? mlen: USBDEV_MAX_XFER; + rv = usb_bulk_write(udev, USBDEV_BULK_EP_WRITE, (char *)bp, tx_size, 100000); + if (rv != tx_size) + { + fprintf(stderr, "%s: usbdev_send(): wrote %d out of %d bytes, err = %s\n", + progname, rv, tx_size, usb_strerror()); + return -1; + } + bp += tx_size; + mlen -= tx_size; + } while (tx_size == USBDEV_MAX_XFER); + + if (verbose > 3) + { + fprintf(stderr, "%s: Sent: ", progname); + + while (i) { + unsigned char c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + i--; + } + fprintf(stderr, "\n"); + } + return 0; +} + +/* + * As calls to usb_bulk_read() result in exactly one USB request, we + * have to buffer the read results ourselves, so the single-char read + * requests performed by the upper layers will be handled. In order + * to do this, we maintain a private buffer of what we've got so far, + * and transparently issue another USB read request if the buffer is + * empty and more data are requested. + */ +static int +usb_fill_buf(usb_dev_handle *udev, int ep) +{ + int rv; + + rv = usb_bulk_read(udev, ep, usbbuf, USBDEV_MAX_XFER, 100000); + if (rv < 0) + { + if (verbose > 1) + fprintf(stderr, "%s: usb_fill_buf(): usb_bulk_read() error %s\n", + progname, usb_strerror()); + return -1; + } + + buflen = rv; + bufptr = 0; + + return 0; +} + +static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbytes) +{ + usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle; + int i, amnt; + unsigned char * p = buf; + + for (i = 0; nbytes > 0;) + { + if (buflen <= bufptr) + { + if (usb_fill_buf(udev, fd->usb.ep) < 0) + return -1; + } + amnt = buflen - bufptr > nbytes? nbytes: buflen - bufptr; + memcpy(buf + i, usbbuf + bufptr, amnt); + bufptr += amnt; + nbytes -= amnt; + i += amnt; + } + + if (verbose > 4) + { + fprintf(stderr, "%s: Recv: ", progname); + + while (i) { + unsigned char c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + i--; + } + fprintf(stderr, "\n"); + } + + return 0; +} + +/* + * This version of recv keeps reading packets until we receive a short + * packet. Then, the entire frame is assembled and returned to the + * user. The length will be unknown in advance, so we return the + * length as the return value of this function, or -1 in case of an + * error. + * + * This is used for the AVRISP mkII device. + */ +static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_t nbytes) +{ + usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle; + int rv, n; + int i; + unsigned char * p = buf; + + n = 0; + do + { + rv = usb_bulk_read(udev, fd->usb.ep, usbbuf, + USBDEV_MAX_XFER, 100000); + if (rv < 0) + { + if (verbose > 1) + fprintf(stderr, "%s: usbdev_recv_frame(): usb_bulk_read(): %s\n", + progname, usb_strerror()); + return -1; + } + + if (rv <= nbytes) + { + memcpy (buf, usbbuf, rv); + buf += rv; + } + + n += rv; + nbytes -= rv; + } + while (rv == USBDEV_MAX_XFER); + + if (nbytes < 0) + return -1; + + if (verbose > 3) + { + i = n; + fprintf(stderr, "%s: Recv: ", progname); + + while (i) { + unsigned char c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + i--; + } + fprintf(stderr, "\n"); + } + return n; +} + +static int usbdev_drain(union filedescriptor *fd, int display) +{ + usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle; + int rv; + + do { + rv = usb_bulk_read(udev, fd->usb.ep, usbbuf, USBDEV_MAX_XFER, 100); + if (rv > 0 && verbose >= 4) + fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n", + progname, rv); + } while (rv > 0); + + return 0; +} + +/* + * Device descriptor for the JTAG ICE mkII. + */ +struct serial_device usb_serdev = +{ + .open = usbdev_open, + .close = usbdev_close, + .send = usbdev_send, + .recv = usbdev_recv, + .drain = usbdev_drain, + .flags = SERDEV_FL_NONE, +}; + +/* + * Device descriptor for the AVRISP mkII. + */ +struct serial_device usb_serdev_frame = +{ + .open = usbdev_open, + .close = usbdev_close, + .send = usbdev_send, + .recv = usbdev_recv_frame, + .drain = usbdev_drain, + .flags = SERDEV_FL_NONE, +}; + +#endif /* HAVE_LIBUSB */ diff --git a/avrdude/usbasp.c b/avrdude/usbasp.c new file mode 100644 index 00000000..e85d0a9f --- /dev/null +++ b/avrdude/usbasp.c @@ -0,0 +1,1131 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2006 Thomas Fischl + * Copyright 2007 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Interface to the USBasp programmer. + * + * See http://www.fischl.de/usbasp/ + */ +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "usbasp.h" + +#if defined(HAVE_LIBUSB) || defined(HAVE_LIBUSB_1_0) + +#ifdef HAVE_LIBUSB_1_0 +# define USE_LIBUSB_1_0 +#endif + +#if defined(USE_LIBUSB_1_0) +# if defined(HAVE_LIBUSB_1_0_LIBUSB_H) +# include +# else +# include +# endif +#else +# include +#endif + +#ifdef USE_LIBUSB_1_0 + +static libusb_context *ctx = NULL; + +static int libusb_to_errno(int result) +{ + switch (result) { + case LIBUSB_SUCCESS: + return 0; + case LIBUSB_ERROR_IO: + return EIO; + case LIBUSB_ERROR_INVALID_PARAM: + return EINVAL; + case LIBUSB_ERROR_ACCESS: + return EACCES; + case LIBUSB_ERROR_NO_DEVICE: + return ENXIO; + case LIBUSB_ERROR_NOT_FOUND: + return ENOENT; + case LIBUSB_ERROR_BUSY: + return EBUSY; +#ifdef ETIMEDOUT + case LIBUSB_ERROR_TIMEOUT: + return ETIMEDOUT; +#endif +#ifdef EOVERFLOW + case LIBUSB_ERROR_OVERFLOW: + return EOVERFLOW; +#endif + case LIBUSB_ERROR_PIPE: + return EPIPE; + case LIBUSB_ERROR_INTERRUPTED: + return EINTR; + case LIBUSB_ERROR_NO_MEM: + return ENOMEM; + case LIBUSB_ERROR_NOT_SUPPORTED: + return ENOSYS; + default: + return ERANGE; + } +} + +#endif + + +/* + * Private data for this programmer. + */ +struct pdata +{ +#ifdef USE_LIBUSB_1_0 + libusb_device_handle *usbhandle; +#else + usb_dev_handle *usbhandle; +#endif + int sckfreq_hz; + unsigned int capabilities; + int use_tpi; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) +#define IMPORT_PDATA(pgm) struct pdata *pdata = PDATA(pgm) + + + +/* Prototypes */ +// interface - management +static void usbasp_setup(PROGRAMMER * pgm); +static void usbasp_teardown(PROGRAMMER * pgm); +// internal functions +static int usbasp_transmit(PROGRAMMER * pgm, unsigned char receive, unsigned char functionid, unsigned char send[4], unsigned char * buffer, int buffersize); +#ifdef USE_LIBUSB_1_0 +static int usbOpenDevice(libusb_device_handle **device, int vendor, char *vendorName, int product, char *productName); +#else +static int usbOpenDevice(usb_dev_handle **device, int vendor, char *vendorName, int product, char *productName); +#endif +// interface - prog. +static int usbasp_open(PROGRAMMER * pgm, char * port); +static void usbasp_close(PROGRAMMER * pgm); +// dummy functions +static void usbasp_disable(PROGRAMMER * pgm); +static void usbasp_enable(PROGRAMMER * pgm); +static void usbasp_display(PROGRAMMER * pgm, const char * p); +// universal functions +static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p); +// SPI specific functions +static int usbasp_spi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]); +static int usbasp_spi_program_enable(PROGRAMMER * pgm, AVRPART * p); +static int usbasp_spi_chip_erase(PROGRAMMER * pgm, AVRPART * p); +static int usbasp_spi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes); +static int usbasp_spi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes); +static int usbasp_spi_set_sck_period(PROGRAMMER *pgm, double sckperiod); +// TPI specific functions +static void usbasp_tpi_send_byte(PROGRAMMER * pgm, uint8_t b); +static int usbasp_tpi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]); +static int usbasp_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p); +static int usbasp_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p); +static int usbasp_tpi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes); +static int usbasp_tpi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes); +static int usbasp_tpi_set_sck_period(PROGRAMMER *pgm, double sckperiod); +static int usbasp_tpi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char * value); +static int usbasp_tpi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char data); + + +/* Interface - management */ +static void usbasp_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: usbasp_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void usbasp_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + +/* Internal functions */ +/* + * wrapper for usb_control_msg call + */ +static int usbasp_transmit(PROGRAMMER * pgm, + unsigned char receive, unsigned char functionid, + unsigned char send[4], unsigned char * buffer, int buffersize) +{ + int nbytes; +#ifdef USE_LIBUSB_1_0 + nbytes = libusb_control_transfer(PDATA(pgm)->usbhandle, + (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | (receive << 7)) & 0xff, + functionid & 0xff, + ((send[1] << 8) | send[0]) & 0xffff, + ((send[3] << 8) | send[2]) & 0xffff, + (char *)buffer, + buffersize & 0xffff, + 5000); + if(nbytes < 0){ + fprintf(stderr, "%s: error: usbasp_transmit: %s\n", progname, strerror(libusb_to_errno(nbytes))); + return -1; + } +#else + nbytes = usb_control_msg(PDATA(pgm)->usbhandle, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | (receive << 7), + functionid, + (send[1] << 8) | send[0], + (send[3] << 8) | send[2], + (char *)buffer, buffersize, + 5000); + if(nbytes < 0){ + fprintf(stderr, "%s: error: usbasp_transmit: %s\n", progname, usb_strerror()); + return -1; + } +#endif + return nbytes; +} + + +/* + * Try to open USB device with given VID, PID, vendor and product name + * Parts of this function were taken from an example code by OBJECTIVE + * DEVELOPMENT Software GmbH (www.obdev.at) to meet conditions for + * shared VID/PID + */ +#ifdef USE_LIBUSB_1_0 +static int usbOpenDevice(libusb_device_handle **device, int vendor, + char *vendorName, int product, char *productName) +{ + libusb_device_handle *handle = NULL; + int errorCode = USB_ERROR_NOTFOUND; + static int didUsbInit = 0; + int j; + int r; + + if(!didUsbInit){ + didUsbInit = 1; + libusb_init(&ctx); + } + + libusb_device **dev_list; + int dev_list_len = libusb_get_device_list(ctx, &dev_list); + + for (j=0; j 1) + fprintf(stderr, + "%s: seen device from vendor ->%s<-\n", + progname, string); + if (strcmp(string, vendorName) == 0){ + r = libusb_get_string_descriptor_ascii(handle, descriptor.iProduct & 0xff, string, sizeof(string)); + if (r < 0) { + errorCode = USB_ERROR_IO; + fprintf(stderr, + "%s: Warning: cannot query product for device: %s\n", + progname, strerror(libusb_to_errno(r))); + } else { + errorCode = USB_ERROR_NOTFOUND; + if (verbose > 1) + fprintf(stderr, + "%s: seen product ->%s<-\n", + progname, string); + if(strcmp(string, productName) == 0) + break; + } + } + } + libusb_close(handle); + handle = NULL; + } + } + if (handle != NULL){ + errorCode = 0; + *device = handle; + } + return errorCode; +} +#else +static int usbOpenDevice(usb_dev_handle **device, int vendor, + char *vendorName, int product, char *productName) +{ +struct usb_bus *bus; +struct usb_device *dev; +usb_dev_handle *handle = NULL; +int errorCode = USB_ERROR_NOTFOUND; +static int didUsbInit = 0; + + if(!didUsbInit){ + didUsbInit = 1; + usb_init(); + } + usb_find_busses(); + usb_find_devices(); + for(bus=usb_get_busses(); bus; bus=bus->next){ + for(dev=bus->devices; dev; dev=dev->next){ + if(dev->descriptor.idVendor == vendor && + dev->descriptor.idProduct == product){ + char string[256]; + int len; + /* we need to open the device in order to query strings */ + handle = usb_open(dev); + if(!handle){ + errorCode = USB_ERROR_ACCESS; + fprintf(stderr, + "%s: Warning: cannot open USB device: %s\n", + progname, usb_strerror()); + continue; + } + if(vendorName == NULL && productName == NULL){ + /* name does not matter */ + break; + } + /* now check whether the names match: */ + len = usb_get_string_simple(handle, dev->descriptor.iManufacturer, + string, sizeof(string)); + if(len < 0){ + errorCode = USB_ERROR_IO; + fprintf(stderr, + "%s: Warning: cannot query manufacturer for device: %s\n", + progname, usb_strerror()); + }else{ + errorCode = USB_ERROR_NOTFOUND; + if (verbose > 1) + fprintf(stderr, + "%s: seen device from vendor ->%s<-\n", + progname, string); + if(strcmp(string, vendorName) == 0){ + len = usb_get_string_simple(handle, dev->descriptor.iProduct, + string, sizeof(string)); + if(len < 0){ + errorCode = USB_ERROR_IO; + fprintf(stderr, + "%s: Warning: cannot query product for device: %s\n", + progname, usb_strerror()); + }else{ + errorCode = USB_ERROR_NOTFOUND; + if (verbose > 1) + fprintf(stderr, + "%s: seen product ->%s<-\n", + progname, string); + if(strcmp(string, productName) == 0) + break; + } + } + } + usb_close(handle); + handle = NULL; + } + } + if(handle) + break; + } + if(handle != NULL){ + errorCode = 0; + *device = handle; + } + return errorCode; +} +#endif + + +/* Interface - prog. */ +static int usbasp_open(PROGRAMMER * pgm, char * port) +{ +#ifdef USE_LIBUSB_1_0 + libusb_init(&ctx); +#else + usb_init(); +#endif + if(strcasecmp(port, "nibobee") == 0) { + if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_NIBOBEE_VID, "www.nicai-systems.com", + USBASP_NIBOBEE_PID, "NIBObee") != 0) { + fprintf(stderr, + "%s: error: could not find USB device " + "\"NIBObee\" with vid=0x%x pid=0x%x\n", + progname, USBASP_NIBOBEE_VID, USBASP_NIBOBEE_PID); + return -1; + + } + } else if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_SHARED_VID, "www.fischl.de", + USBASP_SHARED_PID, "USBasp") != 0) { + + /* check if device with old VID/PID is available */ + if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_OLD_VID, "www.fischl.de", + USBASP_OLD_PID, "USBasp") != 0) { + + /* no USBasp found */ + fprintf(stderr, + "%s: error: could not find USB device " + "\"USBasp\" with vid=0x%x pid=0x%x\n", + progname, USBASP_SHARED_VID, USBASP_SHARED_PID); + return -1; + + } else { + + /* found USBasp with old IDs */ + fprintf(stderr, + "%s: Warning: Found USB device \"USBasp\" with " + "old VID/PID! Please update firmware of USBasp!\n", + progname); + } + } + + return 0; +} + +static void usbasp_close(PROGRAMMER * pgm) +{ + if (PDATA(pgm)->usbhandle!=NULL) { + unsigned char temp[4]; + memset(temp, 0, sizeof(temp)); + + if (PDATA(pgm)->use_tpi) { + usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_DISCONNECT, temp, temp, sizeof(temp)); + } else { + usbasp_transmit(pgm, 1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp)); + } + +#ifdef USE_LIBUSB_1_0 + libusb_close(PDATA(pgm)->usbhandle); +#else + usb_close(PDATA(pgm)->usbhandle); +#endif + } +} + + +/* Dummy functions */ +static void usbasp_disable(PROGRAMMER * pgm) +{ + /* Do nothing. */ + + return; +} + +static void usbasp_enable(PROGRAMMER * pgm) +{ + /* Do nothing. */ + + return; +} + +static void usbasp_display(PROGRAMMER * pgm, const char * p) +{ + return; +} + + +/* Universal functions: for both SPI and TPI */ +static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + int dly; + unsigned char temp[4]; + unsigned char res[4]; + IMPORT_PDATA(pgm); + + + /* get capabilities */ + memset(temp, 0, sizeof(temp)); + if(usbasp_transmit(pgm, 1, USBASP_FUNC_GETCAPABILITIES, temp, res, sizeof(res)) == 4) + pdata->capabilities = res[0] | ((unsigned int)res[1] << 8) | ((unsigned int)res[2] << 16) | ((unsigned int)res[3] << 24); + else + pdata->capabilities = 0; + + pdata->use_tpi = ((pdata->capabilities & USBASP_CAP_TPI) != 0 && (p->flags & AVRPART_HAS_TPI) != 0) ? 1 : 0; + + if(pdata->use_tpi) + { + /* calc tpiclk delay */ + dly = 1500000.0 * pgm->bitclock; + if(dly < 1) + dly = 1; + else if(dly > 2047) + dly = 2047; + temp[0] = dly; + temp[1] = dly >> 8; + + /* connect */ + usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_CONNECT, temp, res, sizeof(res)); + + /* change interface */ + pgm->program_enable = usbasp_tpi_program_enable; + pgm->chip_erase = usbasp_tpi_chip_erase; + pgm->cmd = usbasp_tpi_cmd; + pgm->read_byte = usbasp_tpi_read_byte; + pgm->write_byte = usbasp_tpi_write_byte; + pgm->paged_write = usbasp_tpi_paged_write; + pgm->paged_load = usbasp_tpi_paged_load; + pgm->set_sck_period = usbasp_tpi_set_sck_period; + } + else + { + /* set sck period */ + pgm->set_sck_period(pgm, pgm->bitclock); + + /* connect to target device */ + usbasp_transmit(pgm, 1, USBASP_FUNC_CONNECT, temp, res, sizeof(res)); + + /* change interface */ + pgm->program_enable = usbasp_spi_program_enable; + pgm->chip_erase = usbasp_spi_chip_erase; + pgm->cmd = usbasp_spi_cmd; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + pgm->paged_write = usbasp_spi_paged_write; + pgm->paged_load = usbasp_spi_paged_load; + pgm->set_sck_period = usbasp_spi_set_sck_period; + } + + /* wait, so device is ready to receive commands */ + usleep(100000); + + return pgm->program_enable(pgm, p); +} + +/* SPI specific functions */ +static int usbasp_spi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + int nbytes = + usbasp_transmit(pgm, 1, USBASP_FUNC_TRANSMIT, cmd, res, sizeof(res)); + + if(nbytes != 4){ + fprintf(stderr, "%s: error: wrong responds size\n", + progname); + return -1; + } + + return 0; +} + +static int usbasp_spi_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char res[4]; + unsigned char cmd[4]; + memset(cmd, 0, sizeof(cmd)); + memset(res, 0, sizeof(res)); + + cmd[0] = 0; + + int nbytes = + usbasp_transmit(pgm, 1, USBASP_FUNC_ENABLEPROG, cmd, res, sizeof(res)); + + if ((nbytes != 1) | (res[0] != 0)) { + fprintf(stderr, "%s: error: programm enable: target doesn't answer. %x \n", + progname, res[0]); + return -1; + } + + return 0; +} + +static int usbasp_spi_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + return 0; +} + +static int usbasp_spi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int n; + unsigned char cmd[4]; + int address = 0; + int wbytes = n_bytes; + int blocksize; + unsigned char * buffer = m->buf; + int function; + + if (strcmp(m->desc, "flash") == 0) { + function = USBASP_FUNC_READFLASH; + } else if (strcmp(m->desc, "eeprom") == 0) { + function = USBASP_FUNC_READEEPROM; + } else { + return -2; + } + + /* set blocksize depending on sck frequency */ + if ((PDATA(pgm)->sckfreq_hz > 0) && (PDATA(pgm)->sckfreq_hz < 10000)) { + blocksize = USBASP_READBLOCKSIZE / 10; + } else { + blocksize = USBASP_READBLOCKSIZE; + } + + while (wbytes) { + if (wbytes <= blocksize) { + blocksize = wbytes; + } + wbytes -= blocksize; + + /* set address (new mode) - if firmware on usbasp support newmode, then they use address from this command */ + unsigned char temp[4]; + memset(temp, 0, sizeof(temp)); + cmd[0] = address & 0xFF; + cmd[1] = address >> 8; + cmd[2] = address >> 16; + cmd[3] = address >> 24; + usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); + + /* send command with address (compatibility mode) - if firmware on + usbasp doesn't support newmode, then they use address from this */ + cmd[0] = address & 0xFF; + cmd[1] = address >> 8; + // for compatibility - previous version of usbasp.c doesn't initialize this fields (firmware ignore it) + cmd[2] = 0; + cmd[3] = 0; + + n = usbasp_transmit(pgm, 1, function, cmd, buffer, blocksize); + + if (n != blocksize) { + fprintf(stderr, "%s: error: wrong reading bytes %x\n", + progname, n); + return -3; + } + + buffer += blocksize; + address += blocksize; + + report_progress (address, n_bytes, NULL); + } + + return n_bytes; +} + +static int usbasp_spi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int n; + unsigned char cmd[4]; + int address = 0; + int wbytes = n_bytes; + int blocksize; + unsigned char * buffer = m->buf; + unsigned char blockflags = USBASP_BLOCKFLAG_FIRST; + int function; + + if (strcmp(m->desc, "flash") == 0) { + function = USBASP_FUNC_WRITEFLASH; + } else if (strcmp(m->desc, "eeprom") == 0) { + function = USBASP_FUNC_WRITEEEPROM; + } else { + return -2; + } + + /* set blocksize depending on sck frequency */ + if ((PDATA(pgm)->sckfreq_hz > 0) && (PDATA(pgm)->sckfreq_hz < 10000)) { + blocksize = USBASP_WRITEBLOCKSIZE / 10; + } else { + blocksize = USBASP_WRITEBLOCKSIZE; + } + + while (wbytes) { + + if (wbytes <= blocksize) { + blocksize = wbytes; + blockflags |= USBASP_BLOCKFLAG_LAST; + } + wbytes -= blocksize; + + + /* set address (new mode) - if firmware on usbasp support newmode, then + they use address from this command */ + unsigned char temp[4]; + memset(temp, 0, sizeof(temp)); + cmd[0] = address & 0xFF; + cmd[1] = address >> 8; + cmd[2] = address >> 16; + cmd[3] = address >> 24; + usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); + + /* normal command - firmware what support newmode - use address from previous command, + firmware what doesn't support newmode - ignore previous command and use address from this command */ + + cmd[0] = address & 0xFF; + cmd[1] = address >> 8; + cmd[2] = page_size & 0xFF; + cmd[3] = (blockflags & 0x0F) + ((page_size & 0xF00) >> 4); //TP: Mega128 fix + blockflags = 0; + + n = usbasp_transmit(pgm, 0, function, cmd, buffer, blocksize); + + if (n != blocksize) { + fprintf(stderr, "%s: error: wrong count at writing %x\n", + progname, n); + return -3; + } + + + buffer += blocksize; + address += blocksize; + + report_progress (address, n_bytes, NULL); + } + + return n_bytes; +} + +/* The list of SCK frequencies in Hz supported by USBasp */ +static struct sckoptions_t usbaspSCKoptions[] = { + { USBASP_ISP_SCK_1500, 1500000 }, + { USBASP_ISP_SCK_750, 750000 }, + { USBASP_ISP_SCK_375, 375000 }, + { USBASP_ISP_SCK_187_5, 187500 }, + { USBASP_ISP_SCK_93_75, 93750 }, + { USBASP_ISP_SCK_32, 32000 }, + { USBASP_ISP_SCK_16, 16000 }, + { USBASP_ISP_SCK_8, 8000 }, + { USBASP_ISP_SCK_4, 4000 }, + { USBASP_ISP_SCK_2, 2000 }, + { USBASP_ISP_SCK_1, 1000 }, + { USBASP_ISP_SCK_0_5, 500 } +}; + +/* + * Set sck period (in seconds) + * Find next possible sck period and write it to the programmer. + */ +static int usbasp_spi_set_sck_period(PROGRAMMER *pgm, double sckperiod) +{ + char clockoption = USBASP_ISP_SCK_AUTO; + unsigned char res[4]; + unsigned char cmd[4]; + + memset(cmd, 0, sizeof(cmd)); + memset(res, 0, sizeof(res)); + + /* reset global sck frequency to auto */ + PDATA(pgm)->sckfreq_hz = 0; + + if (sckperiod == 0) { + /* auto sck set */ + + if (verbose >= 1) + fprintf(stderr, "%s: auto set sck period (because given equals null)\n", progname); + + } else { + + int sckfreq = 1 / sckperiod; /* sck in Hz */ + int usefreq = 0; + + if (verbose >= 2) + fprintf(stderr, "%s: try to set SCK period to %g s (= %i Hz)\n", progname, sckperiod, sckfreq); + + if (sckfreq >= usbaspSCKoptions[0].frequency) { + clockoption = usbaspSCKoptions[0].id; + usefreq = usbaspSCKoptions[0].frequency; + } else { + + /* find clock option next to given clock */ + int i; + for (i = 0; i < sizeof(usbaspSCKoptions) / sizeof(usbaspSCKoptions[0]); i++) { + if (sckfreq >= usbaspSCKoptions[i].frequency - 1) { /* subtract 1 to compensate round errors */ + clockoption = usbaspSCKoptions[i].id; + usefreq = usbaspSCKoptions[i].frequency; + break; + } + } + } + + /* save used sck frequency */ + PDATA(pgm)->sckfreq_hz = usefreq; + + fprintf(stderr, "%s: set SCK frequency to %i Hz\n", progname, usefreq); + } + + cmd[0] = clockoption; + + int nbytes = + usbasp_transmit(pgm, 1, USBASP_FUNC_SETISPSCK, cmd, res, sizeof(res)); + + if ((nbytes != 1) | (res[0] != 0)) { + fprintf(stderr, "%s: warning: cannot set sck period. please check for usbasp firmware update.\n", + progname); + return -1; + } + + return 0; +} + +/* TPI specific functions */ +static void usbasp_tpi_send_byte(PROGRAMMER * pgm, uint8_t b) +{ + unsigned char temp[4]; + memset(temp, 0, sizeof(temp)); + + temp[0] = b; + + usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_RAWWRITE, temp, temp, sizeof(temp)); +} + + +static int usbasp_tpi_recv_byte(PROGRAMMER * pgm) +{ + unsigned char temp[4]; + memset(temp, 0, sizeof(temp)); + + if(usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_RAWREAD, temp, temp, sizeof(temp)) != 1) + { + fprintf(stderr, "%s: error: wrong responds size\n", progname); + return -1; + } + + return temp[0]; +} + + +static int usbasp_tpi_nvm_waitbusy(PROGRAMMER * pgm) +{ + int retry; + + + for(retry=50; retry>0; retry--) + { + usbasp_tpi_send_byte(pgm, TPI_OP_SIN(NVMCSR)); + if(usbasp_tpi_recv_byte(pgm) & NVMCSR_BSY) + continue; + return 0; + } + return -1; +} + +static int usbasp_tpi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) +{ + fprintf(stderr, "%s: error: spi_cmd used in TPI mode: not allowed\n", progname); + return -1; +} + +static int usbasp_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + int retry; + + + /* change guard time */ + usbasp_tpi_send_byte(pgm, TPI_OP_SSTCS(TPIPCR)); + usbasp_tpi_send_byte(pgm, TPIPCR_GT_2b); + + /* send SKEY */ + usbasp_tpi_send_byte(pgm, 0xE0); + usbasp_tpi_send_byte(pgm, 0xFF); + usbasp_tpi_send_byte(pgm, 0x88); + usbasp_tpi_send_byte(pgm, 0xD8); + usbasp_tpi_send_byte(pgm, 0xCD); + usbasp_tpi_send_byte(pgm, 0x45); + usbasp_tpi_send_byte(pgm, 0xAB); + usbasp_tpi_send_byte(pgm, 0x89); + usbasp_tpi_send_byte(pgm, 0x12); + + /* check if device is ready */ + for(retry=0; retry<10; retry++) + { + usbasp_tpi_send_byte(pgm, TPI_OP_SLDCS(TPIIR)); + if(usbasp_tpi_recv_byte(pgm) != 0x80) + continue; + usbasp_tpi_send_byte(pgm, TPI_OP_SLDCS(TPISR)); + if((usbasp_tpi_recv_byte(pgm) & TPISR_NVMEN) == 0) + continue; + break; + } + if(retry >= 10) + { + fprintf(stderr, "%s: error: programm enable: target doesn't answer.\n", progname); + return -1; + } + + return 0; +} + +static int usbasp_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + /* Set PR to flash */ + usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0)); + usbasp_tpi_send_byte(pgm, 0x01); + usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(1)); + usbasp_tpi_send_byte(pgm, 0x40); + /* select ERASE */ + usbasp_tpi_send_byte(pgm, TPI_OP_SOUT(NVMCMD)); + usbasp_tpi_send_byte(pgm, NVMCMD_CHIP_ERASE); + /* dummy write */ + usbasp_tpi_send_byte(pgm, TPI_OP_SST_INC); + usbasp_tpi_send_byte(pgm, 0x00); + usbasp_tpi_nvm_waitbusy(pgm); + + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + return 0; +} + +static int usbasp_tpi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes) +{ + unsigned char cmd[4]; + unsigned char* dptr; + int readed, clen, n; + uint16_t pr; + + + dptr = m->buf; + pr = m->offset; + readed = 0; + + while(readed < n_bytes) + { + clen = n_bytes - readed; + if(clen > 32) + clen = 32; + + /* prepare READBLOCK cmd */ + cmd[0] = pr & 0xFF; + cmd[1] = pr >> 8; + cmd[2] = 0; + cmd[3] = 0; + n = usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_READBLOCK, cmd, dptr, clen); + if(n != clen) + { + fprintf(stderr, "%s: error: wrong reading bytes %x\n", progname, n); + return -3; + } + + readed += clen; + pr += clen; + dptr += clen; + + report_progress(readed, n_bytes, NULL); + } + + return n_bytes; +} + +static int usbasp_tpi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes) +{ + unsigned char cmd[4]; + unsigned char dummy[8]; + unsigned char* sptr; + int writed, clen, n; + uint16_t pr; + + + sptr = m->buf; + pr = m->offset; + writed = 0; + + /* Set PR to flash */ + usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0)); + usbasp_tpi_send_byte(pgm, (pr & 0xFF) | 1 ); + usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(1)); + usbasp_tpi_send_byte(pgm, (pr >> 8) ); + /* select SECTIONERASE */ + usbasp_tpi_send_byte(pgm, TPI_OP_SOUT(NVMCMD)); + usbasp_tpi_send_byte(pgm, NVMCMD_SECTION_ERASE); + /* dummy write */ + usbasp_tpi_send_byte(pgm, TPI_OP_SST); + usbasp_tpi_send_byte(pgm, 0x00); + usbasp_tpi_nvm_waitbusy(pgm); + + usleep(p->chip_erase_delay); + + while(writed < n_bytes) + { + clen = n_bytes - writed; + if(clen > 32) + clen = 32; + + /* prepare WRITEBLOCK cmd */ + cmd[0] = pr & 0xFF; + cmd[1] = pr >> 8; + cmd[2] = 0; + cmd[3] = 0; + n = usbasp_transmit(pgm, 0, USBASP_FUNC_TPI_WRITEBLOCK, cmd, sptr, clen); + if(n != clen) + { + fprintf(stderr, "%s: error: wrong count at writing %x\n", progname, n); + return -3; + } + + writed += clen; + pr += clen; + sptr += clen; + + report_progress(writed, n_bytes, NULL); + } + + /* finishing write */ + while(( clen = (-pr) & (m->page_size-1) ) != 0) + { + if(clen > 8) + clen = 8; + + memset(dummy, 0xFF, clen); + + cmd[0] = pr & 0xFF; + cmd[1] = pr >> 8; + cmd[2] = 0; + cmd[3] = 0; + n = usbasp_transmit(pgm, 0, USBASP_FUNC_TPI_WRITEBLOCK, cmd, dummy, clen); + if(n != clen) + { + fprintf(stderr, "%s: error: wrong count at writing %x\n", progname, n); + return -3; + } + + pr += clen; + } + + return n_bytes; +} + +static int usbasp_tpi_set_sck_period(PROGRAMMER *pgm, double sckperiod) +{ + return 0; +} +static int usbasp_tpi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char * value) +{ + unsigned char cmd[4]; + int n; + uint16_t pr; + + + pr = m->offset + addr; + + /* READBLOCK */ + cmd[0] = pr & 0xFF; + cmd[1] = pr >> 8; + cmd[2] = 0; + cmd[3] = 0; + n = usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_READBLOCK, cmd, value, 1); + if(n != 1) + { + fprintf(stderr, "%s: error: wrong reading bytes %x\n", progname, n); + return -3; + } + return 0; +} + +static int usbasp_tpi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char data) +{ + fprintf(stderr, "%s: error: usbasp_write_byte in TPI mode: all writes have to be done at page level\n", progname); + return -1; +} + + +void usbasp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "usbasp"); + + /* + * mandatory functions + */ + + pgm->initialize = usbasp_initialize; + pgm->display = usbasp_display; + pgm->enable = usbasp_enable; + pgm->disable = usbasp_disable; + pgm->program_enable = usbasp_spi_program_enable; + pgm->chip_erase = usbasp_spi_chip_erase; + pgm->cmd = usbasp_spi_cmd; + pgm->open = usbasp_open; + pgm->close = usbasp_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* + * optional functions + */ + + pgm->paged_write = usbasp_spi_paged_write; + pgm->paged_load = usbasp_spi_paged_load; + pgm->setup = usbasp_setup; + pgm->teardown = usbasp_teardown; + pgm->set_sck_period = usbasp_spi_set_sck_period; + +} + + +#else /* HAVE_LIBUSB */ + +static int usbasp_nousb_open (struct programmer_t *pgm, char * name) +{ + fprintf(stderr, "%s: error: no usb support. please compile again with libusb installed.\n", + progname); + + return -1; +} + +void usbasp_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "usbasp"); + + pgm->open = usbasp_nousb_open; +} + +#endif /* HAVE_LIBUSB */ diff --git a/avrdude/usbasp.h b/avrdude/usbasp.h new file mode 100644 index 00000000..91b6e8a8 --- /dev/null +++ b/avrdude/usbasp.h @@ -0,0 +1,149 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2006 Thomas Fischl + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef usbasp_h +#define usbasp_h + +#include "avrpart.h" + +/* USB identifiers */ +#define USBASP_SHARED_VID 0x16C0 /* VOTI */ +#define USBASP_SHARED_PID 0x05DC /* Obdev's free shared PID */ + +#define USBASP_OLD_VID 0x03EB /* ATMEL */ +#define USBASP_OLD_PID 0xC7B4 /* (unoffical) USBasp */ + +#define USBASP_NIBOBEE_VID 0x16C0 /* VOTI */ +#define USBASP_NIBOBEE_PID 0x092F /* NIBObee PID */ + +/* USB function call identifiers */ +#define USBASP_FUNC_CONNECT 1 +#define USBASP_FUNC_DISCONNECT 2 +#define USBASP_FUNC_TRANSMIT 3 +#define USBASP_FUNC_READFLASH 4 +#define USBASP_FUNC_ENABLEPROG 5 +#define USBASP_FUNC_WRITEFLASH 6 +#define USBASP_FUNC_READEEPROM 7 +#define USBASP_FUNC_WRITEEEPROM 8 +#define USBASP_FUNC_SETLONGADDRESS 9 +#define USBASP_FUNC_SETISPSCK 10 +#define USBASP_FUNC_TPI_CONNECT 11 +#define USBASP_FUNC_TPI_DISCONNECT 12 +#define USBASP_FUNC_TPI_RAWREAD 13 +#define USBASP_FUNC_TPI_RAWWRITE 14 +#define USBASP_FUNC_TPI_READBLOCK 15 +#define USBASP_FUNC_TPI_WRITEBLOCK 16 +#define USBASP_FUNC_GETCAPABILITIES 127 + +/* USBASP capabilities */ +#define USBASP_CAP_TPI 0x01 + +/* Block mode flags */ +#define USBASP_BLOCKFLAG_FIRST 1 +#define USBASP_BLOCKFLAG_LAST 2 + +/* Block mode data size */ +#define USBASP_READBLOCKSIZE 200 +#define USBASP_WRITEBLOCKSIZE 200 + +/* ISP SCK speed identifiers */ +#define USBASP_ISP_SCK_AUTO 0 +#define USBASP_ISP_SCK_0_5 1 /* 500 Hz */ +#define USBASP_ISP_SCK_1 2 /* 1 kHz */ +#define USBASP_ISP_SCK_2 3 /* 2 kHz */ +#define USBASP_ISP_SCK_4 4 /* 4 kHz */ +#define USBASP_ISP_SCK_8 5 /* 8 kHz */ +#define USBASP_ISP_SCK_16 6 /* 16 kHz */ +#define USBASP_ISP_SCK_32 7 /* 32 kHz */ +#define USBASP_ISP_SCK_93_75 8 /* 93.75 kHz */ +#define USBASP_ISP_SCK_187_5 9 /* 187.5 kHz */ +#define USBASP_ISP_SCK_375 10 /* 375 kHz */ +#define USBASP_ISP_SCK_750 11 /* 750 kHz */ +#define USBASP_ISP_SCK_1500 12 /* 1.5 MHz */ + +/* TPI instructions */ +#define TPI_OP_SLD 0x20 +#define TPI_OP_SLD_INC 0x24 +#define TPI_OP_SST 0x60 +#define TPI_OP_SST_INC 0x64 +#define TPI_OP_SSTPR(a) (0x68 | (a)) +#define TPI_OP_SIN(a) (0x10 | (((a)<<1)&0x60) | ((a)&0x0F) ) +#define TPI_OP_SOUT(a) (0x90 | (((a)<<1)&0x60) | ((a)&0x0F) ) +#define TPI_OP_SLDCS(a) (0x80 | ((a)&0x0F) ) +#define TPI_OP_SSTCS(a) (0xC0 | ((a)&0x0F) ) +#define TPI_OP_SKEY 0xE0 + +/* TPI control/status registers */ +#define TPIIR 0xF +#define TPIPCR 0x2 +#define TPISR 0x0 + +// TPIPCR bits +#define TPIPCR_GT_2 0x04 +#define TPIPCR_GT_1 0x02 +#define TPIPCR_GT_0 0x01 +#define TPIPCR_GT_128b 0x00 +#define TPIPCR_GT_64b 0x01 +#define TPIPCR_GT_32b 0x02 +#define TPIPCR_GT_16b 0x03 +#define TPIPCR_GT_8b 0x04 +#define TPIPCR_GT_4b 0x05 +#define TPIPCR_GT_2b 0x06 +#define TPIPCR_GT_0b 0x07 + +// TPISR bits +#define TPISR_NVMEN 0x02 + +/* NVM registers */ +#define NVMCSR 0x32 +#define NVMCMD 0x33 + +// NVMCSR bits +#define NVMCSR_BSY 0x80 + +// NVMCMD values +#define NVMCMD_NOP 0x00 +#define NVMCMD_CHIP_ERASE 0x10 +#define NVMCMD_SECTION_ERASE 0x14 +#define NVMCMD_WORD_WRITE 0x1D + + +typedef struct sckoptions_t { + int id; + double frequency; +} CLOCKOPTIONS; + +/* USB error identifiers */ +#define USB_ERROR_NOTFOUND 1 +#define USB_ERROR_ACCESS 2 +#define USB_ERROR_IO 3 + +#ifdef __cplusplus +extern "C" { +#endif + +void usbasp_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif /* usbasp_h */ diff --git a/avrdude/usbdevs.h b/avrdude/usbdevs.h new file mode 100644 index 00000000..0c36f816 --- /dev/null +++ b/avrdude/usbdevs.h @@ -0,0 +1,43 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2006 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * defines for the USB interface + */ + +#ifndef usbdevs_h +#define usbdevs_h + +#define USB_VENDOR_ATMEL 1003 +#define USB_DEVICE_JTAGICEMKII 0x2103 +#define USB_DEVICE_AVRISPMKII 0x2104 +#define USB_DEVICE_STK600 0x2106 +#define USB_DEVICE_AVRDRAGON 0x2107 + +/* + * Should we query the endpoint number and max transfer size from USB? + * After all, the JTAG ICE mkII docs document these values. + */ +#define USBDEV_BULK_EP_WRITE 0x02 +#define USBDEV_BULK_EP_READ 0x82 +#define USBDEV_MAX_XFER 64 + +#endif /* usbdevs_h */ diff --git a/avrdude/usbtiny.c b/avrdude/usbtiny.c new file mode 100644 index 00000000..56467577 --- /dev/null +++ b/avrdude/usbtiny.c @@ -0,0 +1,581 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2007 Dick Streefland, adapted for 5.4 by Limor Fried + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Driver for "usbtiny"-type programmers + * Please see http://www.xs4all.nl/~dicks/avr/usbtiny/ + * and http://www.ladyada.net/make/usbtinyisp/ + * For example schematics and detailed documentation + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "config.h" +#include "usbtiny.h" + +#if defined(HAVE_LIBUSB) // we use LIBUSB to talk to the board +#include + +#ifndef HAVE_UINT_T +typedef unsigned int uint_t; +#endif +#ifndef HAVE_ULONG_T +typedef unsigned long ulong_t; +#endif + +extern int avr_write_byte_default ( PROGRAMMER* pgm, AVRPART* p, + AVRMEM* mem, ulong_t addr, + unsigned char data ); +/* + * Private data for this programmer. + */ +struct pdata +{ + usb_dev_handle *usb_handle; + int sck_period; + int chunk_size; + int retries; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +// ---------------------------------------------------------------------- + +static void usbtiny_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: usbtiny_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void usbtiny_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + +// Wrapper for simple usb_control_msg messages +static int usb_control (PROGRAMMER * pgm, + unsigned int requestid, unsigned int val, unsigned int index ) +{ + int nbytes; + nbytes = usb_control_msg( PDATA(pgm)->usb_handle, + USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + requestid, + val, index, // 2 bytes each of data + NULL, 0, // no data buffer in control messge + USB_TIMEOUT ); // default timeout + if(nbytes < 0){ + fprintf(stderr, "\n%s: error: usbtiny_transmit: %s\n", progname, usb_strerror()); + return -1; + } + + return nbytes; +} + +// Wrapper for simple usb_control_msg messages to receive data from programmer +static int usb_in (PROGRAMMER * pgm, + unsigned int requestid, unsigned int val, unsigned int index, + unsigned char* buffer, int buflen, int bitclk ) +{ + int nbytes; + int timeout; + int i; + + // calculate the amout of time we expect the process to take by + // figuring the bit-clock time and buffer size and adding to the standard USB timeout. + timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; + + for (i = 0; i < 10; i++) { + nbytes = usb_control_msg( PDATA(pgm)->usb_handle, + USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + requestid, + val, index, + (char *)buffer, buflen, + timeout); + if (nbytes == buflen) { + return nbytes; + } + PDATA(pgm)->retries++; + } + fprintf(stderr, "\n%s: error: usbtiny_receive: %s (expected %d, got %d)\n", + progname, usb_strerror(), buflen, nbytes); + return -1; +} + +// Report the number of retries, and reset the counter. +static void check_retries (PROGRAMMER * pgm, const char* operation) +{ + if (PDATA(pgm)->retries > 0 && quell_progress < 2) { + fprintf(stderr, "%s: %d retries during %s\n", progname, + PDATA(pgm)->retries, operation); + } + PDATA(pgm)->retries = 0; +} + +// Wrapper for simple usb_control_msg messages to send data to programmer +static int usb_out (PROGRAMMER * pgm, + unsigned int requestid, unsigned int val, unsigned int index, + unsigned char* buffer, int buflen, int bitclk ) +{ + int nbytes; + int timeout; + + // calculate the amout of time we expect the process to take by + // figuring the bit-clock time and buffer size and adding to the standard USB timeout. + timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; + + nbytes = usb_control_msg( PDATA(pgm)->usb_handle, + USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + requestid, + val, index, + (char *)buffer, buflen, + timeout); + if (nbytes != buflen) { + fprintf(stderr, "\n%s: error: usbtiny_send: %s (expected %d, got %d)\n", + progname, usb_strerror(), buflen, nbytes); + return -1; + } + + return nbytes; +} + +// Sometimes we just need to know the SPI command for the part to perform +// a function. Here we wrap this request for an operation so that we +// can just specify the part and operation and it'll do the right stuff +// to get the information from AvrDude and send to the USBtiny +static int usbtiny_avr_op (PROGRAMMER * pgm, AVRPART * p, + int op, + unsigned char res[4]) +{ + unsigned char cmd[4]; + + if (p->op[op] == NULL) { + fprintf( stderr, "Operation %d not defined for this chip!\n", op ); + return -1; + } + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[op], cmd); + + return pgm->cmd(pgm, cmd, res); +} + +// ---------------------------------------------------------------------- + +/* Find a device with the correct VID/PID match for USBtiny */ + +static int usbtiny_open(PROGRAMMER* pgm, char* name) +{ + struct usb_bus *bus; + struct usb_device *dev = 0; + char *bus_name = NULL; + char *dev_name = NULL; + + // if no -P was given or '-P usb' was given + if(name == default_parallel || strcmp(name, "usb") == 0) + name = NULL; + else { + // calculate bus and device names from -P option + const size_t usb_len = strlen("usb"); + if(strncmp(name, "usb", usb_len) == 0 && ':' == name[usb_len]) { + bus_name = name + usb_len + 1; + dev_name = strchr(bus_name, ':'); + if(NULL != dev_name) + *dev_name++ = '\0'; + } + } + + usb_init(); // initialize the libusb system + usb_find_busses(); // have libusb scan all the usb busses available + usb_find_devices(); // have libusb scan all the usb devices available + + PDATA(pgm)->usb_handle = NULL; + + // now we iterate through all the busses and devices + for ( bus = usb_busses; bus; bus = bus->next ) { + for ( dev = bus->devices; dev; dev = dev->next ) { + if (dev->descriptor.idVendor == USBTINY_VENDOR + && dev->descriptor.idProduct == USBTINY_PRODUCT ) { // found match? + if(verbose) + printf("avrdude: usbdev_open(): Found USBtinyISP, bus:device: %s:%s\n", bus->dirname, dev->filename); + // if -P was given, match device by device name and bus name + if(name != NULL && + (NULL == dev_name || + strcmp(bus->dirname, bus_name) || + strcmp(dev->filename, dev_name))) + continue; + PDATA(pgm)->usb_handle = usb_open(dev); // attempt to connect to device + + // wrong permissions or something? + if (!PDATA(pgm)->usb_handle) { + fprintf(stderr, "%s: Warning: cannot open USB device: %s\n", + progname, usb_strerror()); + continue; + } + } + } + } + + if(NULL != name && NULL == dev_name) { + fprintf(stderr, "%s: Error: Invalid -P value: '%s'\n", progname, name); + fprintf(stderr, "%sUse -P usb:bus:device\n", progbuf); + return -1; + } + if (!PDATA(pgm)->usb_handle) { + fprintf( stderr, "%s: Error: Could not find USBtiny device (0x%x/0x%x)\n", + progname, USBTINY_VENDOR, USBTINY_PRODUCT ); + return -1; + } + + return 0; // If we got here, we must have found a good USB device +} + +/* Clean up the handle for the usbtiny */ +static void usbtiny_close ( PROGRAMMER* pgm ) +{ + if (! PDATA(pgm)->usb_handle) { + return; // not a valid handle, bail! + } + usb_close(PDATA(pgm)->usb_handle); // ask libusb to clean up + PDATA(pgm)->usb_handle = NULL; +} + +/* A simple calculator function determines the maximum size of data we can + shove through a USB connection without getting errors */ +static void usbtiny_set_chunk_size (PROGRAMMER * pgm, int period) +{ + PDATA(pgm)->chunk_size = CHUNK_SIZE; // start with the maximum (default) + while (PDATA(pgm)->chunk_size > 8 && period > 16) { + // Reduce the chunk size for a slow SCK to reduce + // the maximum time of a single USB transfer. + PDATA(pgm)->chunk_size >>= 1; + period >>= 1; + } +} + +/* Given a SCK bit-clock speed (in useconds) we verify its an OK speed and tell the + USBtiny to update itself to the new frequency */ +static int usbtiny_set_sck_period (PROGRAMMER *pgm, double v) +{ + PDATA(pgm)->sck_period = (int)(v * 1e6 + 0.5); // convert from us to 'int', the 0.5 is for rounding up + + // Make sure its not 0, as that will confuse the usbtiny + if (PDATA(pgm)->sck_period < SCK_MIN) + PDATA(pgm)->sck_period = SCK_MIN; + + // We can't go slower, due to the byte-size of the clock variable + if (PDATA(pgm)->sck_period > SCK_MAX) + PDATA(pgm)->sck_period = SCK_MAX; + + if (verbose) { + fprintf(stderr, "%s: Setting SCK period to %d usec\n", progname, + PDATA(pgm)->sck_period ); + } + + // send the command to the usbtiny device. + // MEME: for at90's fix resetstate? + if (usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW) < 0) + return -1; + + // with the new speed, we'll have to update how much data we send per usb transfer + usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period); + return 0; +} + + +static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) +{ + unsigned char res[4]; // store the response from usbtinyisp + + // Check for bit-clock and tell the usbtiny to adjust itself + if (pgm->bitclock > 0.0) { + // -B option specified: convert to valid range for sck_period + usbtiny_set_sck_period(pgm, pgm->bitclock); + } else { + // -B option not specified: use default + PDATA(pgm)->sck_period = SCK_DEFAULT; + if (verbose) { + fprintf(stderr, "%s: Using SCK period of %d usec\n", + progname, PDATA(pgm)->sck_period ); + } + if (usb_control(pgm, USBTINY_POWERUP, + PDATA(pgm)->sck_period, RESET_LOW ) < 0) + return -1; + usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period); + } + + // Let the device wake up. + usleep(50000); + + // Attempt to use the underlying avrdude methods to connect (MEME: is this kosher?) + if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) { + // no response, RESET and try again + if (usb_control(pgm, USBTINY_POWERUP, + PDATA(pgm)->sck_period, RESET_HIGH) < 0 || + usb_control(pgm, USBTINY_POWERUP, + PDATA(pgm)->sck_period, RESET_LOW) < 0) + return -1; + usleep(50000); + if ( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) { + // give up + return -1; + } + } + return 0; +} + +/* Tell the USBtiny to release the output pins, etc */ +static void usbtiny_powerdown(PROGRAMMER * pgm) +{ + if (!PDATA(pgm)->usb_handle) { + return; // wasn't connected in the first place + } + usb_control(pgm, USBTINY_POWERDOWN, 0, 0); // Send USB control command to device +} + +/* Send a 4-byte SPI command to the USBtinyISP for execution + This procedure is used by higher-level Avrdude procedures */ +static int usbtiny_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) +{ + int nbytes; + + // Make sure its empty so we don't read previous calls if it fails + memset(res, '\0', 4 ); + + nbytes = usb_in( pgm, USBTINY_SPI, + (cmd[1] << 8) | cmd[0], // convert to 16-bit words + (cmd[3] << 8) | cmd[2], // " + res, 4, 8 * PDATA(pgm)->sck_period ); + if (nbytes < 0) + return -1; + check_retries(pgm, "SPI command"); + if (verbose > 1) { + // print out the data we sent and received + fprintf(stderr, "CMD: [%02x %02x %02x %02x] [%02x %02x %02x %02x]\n", + cmd[0], cmd[1], cmd[2], cmd[3], + res[0], res[1], res[2], res[3] ); + } + return ((nbytes == 4) && // should have read 4 bytes + res[2] == cmd[1]); // AVR's do a delayed-echo thing +} + +/* Send the chip-erase command */ +static int usbtiny_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "Chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + // get the command for erasing this chip and transmit to avrdude + if (! usbtiny_avr_op( pgm, p, AVR_OP_CHIP_ERASE, res )) { + return -1; + } + usleep( p->chip_erase_delay ); + + // prepare for further instruction + pgm->initialize(pgm, p); + + return 0; +} + +// These are required functions but don't actually do anything +static void usbtiny_enable ( PROGRAMMER* pgm ) {} + +static void usbtiny_disable ( PROGRAMMER* pgm ) {} + + +/* To speed up programming and reading, we do a 'chunked' read. + * We request just the data itself and the USBtiny uses the SPI function + * given to read in the data. Much faster than sending a 4-byte SPI request + * per byte +*/ +static int usbtiny_paged_load (PROGRAMMER * pgm, AVRPART * p, AVRMEM* m, + int page_size, int n_bytes ) +{ + int i; + int chunk; + int function; + + + // First determine what we're doing + if (strcmp( m->desc, "flash" ) == 0) { + function = USBTINY_FLASH_READ; + } else { + function = USBTINY_EEPROM_READ; + } + + for (i = 0; i < n_bytes; i += chunk) { + chunk = PDATA(pgm)->chunk_size; // start with the maximum chunk size possible + + // If we want to xmit less than a chunk, thats OK + if (chunk > n_bytes-i) + chunk = n_bytes - i; + + // Send the chunk of data to the USBtiny with the function we want + // to perform + if (usb_in(pgm, + function, // EEPROM or flash + 0, // delay between SPI commands + i, // index + m->buf + i, // pointer to where we store data + chunk, // number of bytes + 32 * PDATA(pgm)->sck_period) // each byte gets turned into a 4-byte SPI cmd + < 0) { + // usb_in() multiplies this per byte. + return -1; + } + + // Tell avrdude how we're doing to provide user feedback + report_progress(i + chunk, n_bytes, NULL ); + } + + check_retries(pgm, "read"); + return n_bytes; +} + +/* To speed up programming and reading, we do a 'chunked' write. + * We send just the data itself and the USBtiny uses the SPI function + * given to write the data. Much faster than sending a 4-byte SPI request + * per byte. +*/ +static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int i; + int chunk; // Size of data to write at once + int next; + int function; // which SPI command to use + int delay; // delay required between SPI commands + + // First determine what we're doing + if (strcmp( m->desc, "flash" ) == 0) { + function = USBTINY_FLASH_WRITE; + } else { + function = USBTINY_EEPROM_WRITE; + } + + delay = 0; + if (! m->paged) { + // Does this chip not support paged writes? + i = (m->readback[1] << 8) | m->readback[0]; + if (usb_control(pgm, USBTINY_POLL_BYTES, i, 0 ) < 0) + return -1; + delay = m->max_write_delay; + } + + for (i=0; i < n_bytes; i=next) { + // start with the max chunk size + chunk = PDATA(pgm)->chunk_size; + + // we can only write a page at a time anyways + if (m->paged && chunk > page_size) + chunk = page_size; + + // if there's less data remaining than one chunk + if (chunk > n_bytes-i) + chunk = n_bytes - i; + + if (usb_out(pgm, + function, // Flash or EEPROM + delay, // How much to wait between each byte + i, // Index of data + m->buf + i, // Pointer to data + chunk, // Number of bytes to write + 32 * PDATA(pgm)->sck_period + delay // each byte gets turned into a + // 4-byte SPI cmd usb_out() multiplies + // this per byte. Then add the cmd-delay + ) < 0) { + return -1; + } + + next = i + chunk; // Calculate what address we're at now + if (m->paged + && ((next % page_size) == 0 || next == n_bytes) ) { + // If we're at a page boundary, send the SPI command to flush it. + avr_write_page(pgm, p, m, (unsigned long) i); + } + + report_progress( next, n_bytes, NULL ); + } + return n_bytes; +} + +extern void usbtiny_initpgm ( PROGRAMMER* pgm ) +{ + strcpy(pgm->type, "USBtiny"); + + /* Mandatory Functions */ + pgm->initialize = usbtiny_initialize; + pgm->enable = usbtiny_enable; + pgm->disable = usbtiny_disable; + pgm->program_enable = NULL; + pgm->chip_erase = usbtiny_chip_erase; + pgm->cmd = usbtiny_cmd; + pgm->open = usbtiny_open; + pgm->close = usbtiny_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* Optional Functions */ + pgm->powerup = NULL; + pgm->powerdown = usbtiny_powerdown; + pgm->paged_load = usbtiny_paged_load; + pgm->paged_write = usbtiny_paged_write; + pgm->set_sck_period = usbtiny_set_sck_period; + pgm->setup = usbtiny_setup; + pgm->teardown = usbtiny_teardown; +} + +#else /* !HAVE_LIBUSB */ + +// Give a proper error if we were not compiled with libusb + +static int usbtiny_nousb_open(struct programmer_t *pgm, char * name) +{ + fprintf(stderr, "%s: error: no usb support. Please compile again with libusb installed.\n", + progname); + + return -1; +} + +void usbtiny_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "usbtiny"); + + pgm->open = usbtiny_nousb_open; +} + +#endif /* HAVE_LIBUSB */ diff --git a/avrdude/usbtiny.h b/avrdude/usbtiny.h new file mode 100644 index 00000000..77f9a42e --- /dev/null +++ b/avrdude/usbtiny.h @@ -0,0 +1,76 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2007 Limor Fried + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef usbtiny_h +#define usbtiny_h + +#include "avrpart.h" + +// these are specifically assigned to USBtiny, +// if you need your own VID and PIDs you can get them for cheap from +// www.mecanique.co.uk so please don't reuse these. Thanks! +#define USBTINY_VENDOR 0x1781 +#define USBTINY_PRODUCT 0x0C9F + +// Generic requests to the USBtiny +#define USBTINY_ECHO 0 // echo test +#define USBTINY_READ 1 // read byte (wIndex:address) +#define USBTINY_WRITE 2 // write byte (wIndex:address, wValue:value) +#define USBTINY_CLR 3 // clear bit (wIndex:address, wValue:bitno) +#define USBTINY_SET 4 // set bit (wIndex:address, wValue:bitno) + +// Programming requests +#define USBTINY_POWERUP 5 // apply power (wValue:SCK-period, wIndex:RESET) +#define USBTINY_POWERDOWN 6 // remove power from chip +#define USBTINY_SPI 7 // issue SPI command (wValue:c1c0, wIndex:c3c2) +#define USBTINY_POLL_BYTES 8 // set poll bytes for write (wValue:p1p2) +#define USBTINY_FLASH_READ 9 // read flash (wIndex:address) +#define USBTINY_FLASH_WRITE 10 // write flash (wIndex:address, wValue:timeout) +#define USBTINY_EEPROM_READ 11 // read eeprom (wIndex:address) +#define USBTINY_EEPROM_WRITE 12 // write eeprom (wIndex:address, wValue:timeout) + + + +// Flags to indicate how to set RESET on power up +#define RESET_LOW 0 +#define RESET_HIGH 1 + +// The SCK speed can be set by avrdude, to allow programming of slow-clocked parts +#define SCK_MIN 1 // usec delay (target clock >= 4 MHz) +#define SCK_MAX 250 // usec (target clock >= 16 KHz) +#define SCK_DEFAULT 10 // usec (target clock >= 0.4 MHz) + +// How much data, max, do we want to send in one USB packet? +#define CHUNK_SIZE 128 // must be power of 2 less than 256 + +// The default USB Timeout +#define USB_TIMEOUT 500 // msec + +#ifdef __cplusplus +extern "C" { +#endif + +void usbtiny_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif /* usbtiny_h */ diff --git a/avrdude/windows/.cvsignore b/avrdude/windows/.cvsignore new file mode 100644 index 00000000..601c4fbf --- /dev/null +++ b/avrdude/windows/.cvsignore @@ -0,0 +1,4 @@ +.cvsignore +.deps +Makefile +Makefile.in diff --git a/avrdude/windows/Makefile.am b/avrdude/windows/Makefile.am new file mode 100644 index 00000000..6a03a18e --- /dev/null +++ b/avrdude/windows/Makefile.am @@ -0,0 +1,58 @@ +# +# avrdude - A Downloader/Uploader for AVR device programmers +# Copyright (C) 2003 Theodore A. Roth +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# $Id$ +# + +# +# This Makefile will only be used on windows based systems. +# + +local_install_list = \ + giveio.sys \ + install_giveio.bat \ + remove_giveio.bat \ + status_giveio.bat + +EXTRA_DIST = \ + giveio.c \ + $(local_install_list) + +bin_PROGRAMS = loaddrv + +loaddrv_SOURCES = \ + loaddrv.c \ + loaddrv.h + +install-exec-local: + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(local_install_list)'; for file in $$list; do \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) \ + $(srcdir)/$$file $(DESTDIR)$(bindir)/$$file"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $(srcdir)/$$file \ + $(DESTDIR)$(bindir)/$$file; \ + done + +uninstall-local: + @for file in $(local_install_list); do \ + echo " rm -f $(DESTDIR)$(bindir)/$$file"; \ + rm -f $(DESTDIR)$(bindir)/$$file; \ + done + diff --git a/avrdude/windows/giveio.c b/avrdude/windows/giveio.c new file mode 100644 index 00000000..f752a293 --- /dev/null +++ b/avrdude/windows/giveio.c @@ -0,0 +1,168 @@ +/********************************************************************* + +Author: Dale Roberts +Date: 8/30/95 +Program: GIVEIO.SYS +Compile: Use DDK BUILD facility + +Purpose: Give direct port I/O access to a user mode process. + +*********************************************************************/ +#include + +/* + * The name of our device driver. + */ +#define DEVICE_NAME_STRING L"giveio" + +/* + * This is the "structure" of the IOPM. It is just a simple + * character array of length 0x2000. + * + * This holds 8K * 8 bits -> 64K bits of the IOPM, which maps the + * entire 64K I/O space of the x86 processor. Any 0 bits will give + * access to the corresponding port for user mode processes. Any 1 + * bits will disallow I/O access to the corresponding port. + */ +#define IOPM_SIZE 0x2000 +typedef UCHAR IOPM[IOPM_SIZE]; + +/* + * This will hold simply an array of 0's which will be copied + * into our actual IOPM in the TSS by Ke386SetIoAccessMap(). + * The memory is allocated at driver load time. + */ +IOPM *IOPM_local = 0; + +/* + * These are the two undocumented calls that we will use to give + * the calling process I/O access. + * + * Ke386IoSetAccessMap() copies the passed map to the TSS. + * + * Ke386IoSetAccessProcess() adjusts the IOPM offset pointer so that + * the newly copied map is actually used. Otherwise, the IOPM offset + * points beyond the end of the TSS segment limit, causing any I/O + * access by the user mode process to generate an exception. + */ +void Ke386SetIoAccessMap(int, IOPM *); +void Ke386QueryIoAccessMap(int, IOPM *); +void Ke386IoSetAccessProcess(PEPROCESS, int); + +/********************************************************************* + Release any allocated objects. +*********************************************************************/ +VOID GiveioUnload(IN PDRIVER_OBJECT DriverObject) +{ + WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; + UNICODE_STRING uniDOSString; + + if(IOPM_local) + MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM)); + + RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); + IoDeleteSymbolicLink (&uniDOSString); + IoDeleteDevice(DriverObject->DeviceObject); +} + +/********************************************************************* + Set the IOPM (I/O permission map) of the calling process so that it +is given full I/O access. Our IOPM_local[] array is all zeros, so +the IOPM will be all zeros. If OnFlag is 1, the process is given I/O +access. If it is 0, access is removed. +*********************************************************************/ +VOID SetIOPermissionMap(int OnFlag) +{ + Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag); + Ke386SetIoAccessMap(1, IOPM_local); +} + +void GiveIO(void) +{ + SetIOPermissionMap(1); +} + +/********************************************************************* + Service handler for a CreateFile() user mode call. + + This routine is entered in the driver object function call table by +the DriverEntry() routine. When the user mode application calls +CreateFile(), this routine gets called while still in the context of +the user mode application, but with the CPL (the processor's Current +Privelege Level) set to 0. This allows us to do kernel mode +operations. GiveIO() is called to give the calling process I/O +access. All the user mode application needs do to obtain I/O access +is open this device with CreateFile(). No other operations are +required. +*********************************************************************/ +NTSTATUS GiveioCreateDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) +{ + GiveIO(); // give the calling process I/O access + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +/********************************************************************* + Driver Entry routine. + + This routine is called only once after the driver is initially +loaded into memory. It allocates everything necessary for the +driver's operation. In our case, it allocates memory for our IOPM +array, and creates a device which user mode applications can open. +It also creates a symbolic link to the device driver. This allows +a user mode application to access our driver using the \\.\giveio +notation. +*********************************************************************/ +NTSTATUS DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +{ + PDEVICE_OBJECT deviceObject; + NTSTATUS status; + WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING; + WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; + UNICODE_STRING uniNameString, uniDOSString; + + // + // Allocate a buffer for the local IOPM and zero it. + // + IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM)); + if(IOPM_local == 0) + return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(IOPM_local, sizeof(IOPM)); + + // + // Set up device driver name and device object. + // + RtlInitUnicodeString(&uniNameString, NameBuffer); + RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); + + status = IoCreateDevice(DriverObject, 0, + &uniNameString, + FILE_DEVICE_UNKNOWN, + 0, FALSE, &deviceObject); + + if(!NT_SUCCESS(status)) + return status; + + status = IoCreateSymbolicLink (&uniDOSString, &uniNameString); + + if (!NT_SUCCESS(status)) + return status; + + // + // Initialize the Driver Object with driver's entry points. + // All we require are the Create and Unload operations. + // + DriverObject->MajorFunction[IRP_MJ_CREATE] = GiveioCreateDispatch; + DriverObject->DriverUnload = GiveioUnload; + return STATUS_SUCCESS; +} + diff --git a/avrdude/windows/giveio.sys b/avrdude/windows/giveio.sys new file mode 100644 index 0000000000000000000000000000000000000000..62a0cb66ffda02c19a6db878b32f5b4342131258 GIT binary patch literal 5248 zcmd^CZ)j6j6hCRBMmIP2ry@?=)5U#~P?J_Q~DG1vK2QqXUF6f|xRgirU2M)?mD6AiZb|Ay;?VNYtea$mB>b8%& z?Y-x|-#Pc3bI*JC+>_W#??OEQc(I!%z&WJUWNWK{KQQMbgI#l3I`=-F;GC%PN7@t5^AL)$ulfsAn1c-jvxkwH)A8 z#Aji-=OIsBaKZynu495Xk;>T1BFvhJ<_CZ&M^rlW}Q4WrDP4+WVAE9U+`pa=Mb!G61{qnPRZtrbwJ71MEzkUy09? z^T*~J_r7q!@AW|G$d!dtgQt!?FX00ij}3za@CiM{&4wE!&~~L1yB+T_8)oS#b{l8c zaW)zAnFqaQ!!4Yr_D$Y=<)Rl%!;i={MB;M`Xvl0PMI)ZMS$se~&VDvc^U~Y`j+0Tp zFH{cwbUeJ_czB)Ju!y3e@3&Q zSsq()?gNb5Z|bDAp-}le_y86@FSX5-VvF&~X4*uLd9@TfS!$c_iPP*(DY4iyIp!My z{M+0+0(;GdJC?TBH<#KLOR;&{{cVPT&EL{BUOSdTr3eK+<2?1!-Xu%E_$0sB?# zbJ+il{6*;0B1%p%l!!8}W)y%+4$^lxKcMB*OjIo#0N7a9Yvei$s*xzD8O&yVhOQQd z0CZ0*->xf4msV&^XNHw*Ov!8dVeoqPD4`wO`xK*73uiJ)u^3B_LLEapHN+Vj*EM3o zWwhI&7_DQvt`rQ8{)y;dtCk-n7kib1V@eUz#|1=NbtP>mZXdsKaK0NAy$k2?NTclC z9u^F(ct9`Y0?HxWcXew*s4Mt#a5$(1j|ATiz85?d{4#hwxDYghYeP?kwuW|w)X;08 zw?d`RN1>CLc^|w{zL#uqqLc$EzgamB-(_G>&2gvx!ux5cuJyTOHl0(F+3ZL%s}?c( z1IZzETv0Wf1Tw(0A!S1Py6ZjFpB2x*WRVU=y(fhuB?{IE<9hs#o@Y7RqLi??o{t?p z5~54?m>y+dY{=g}wH|;DX1#~5BH~c<0&djN^PQsy^Nb_IW`Qizb4I9Vxl7Nqqh}-P zAx~MW^rtM;<8$euo0rzqd%nVPm92&QV_i-Vb>c&|mKs@QH;#WhooQAe3?2qMXKTt*dEkQK-jl>wBS$+ZN?eW@~LtTa=rb42|OVMftp1#%+soIg=6C zvg@Kx@z}Djj?RnFR`a~jmV58t3T52>&^^NZ!QSOG%;i!A`&j8n~@>U;EdmK47r8~&*}_0i)6x%219;C z1@F6%N0Gs^1e19KZSi-?kSRoFU8^o2!oO!Gvko=$)5MTwMEH4U$Ox|DZ;&Bdk??%T zkX=Z4HfG2m5`GsjaWrI1Ad+&d;B_6F}DKNZoj=Fr;;hJIMy0jUnF z0!b8dS~@E?K}$=jRZeYd?T|a-(U{!g4~JWVG)8F9Xec_53eCo8P-)1}U}2UBTQ}se zEkTQINn5&z$-4|Gsx`agik?@CMO7Wsy^d;3$7w!YTh z&Uk-!?~?G{VXPIvnxSKntr5TqrZ|k^0M-bd=ywkVjpG&Js`V(S@ z=--v-+LMZe`@>cxV*QTxUVkT$RPl#hau9#?@t+>W!$m7u{BH)jvm|@Bn2@a-i+;E8 PM)wu}O~A4%=P>#=i9DqO literal 0 HcmV?d00001 diff --git a/avrdude/windows/install_giveio.bat b/avrdude/windows/install_giveio.bat new file mode 100755 index 00000000..4a02b093 --- /dev/null +++ b/avrdude/windows/install_giveio.bat @@ -0,0 +1,34 @@ +@set DIRVERNAME=giveio +@set DIRVERFILE=%DIRVERNAME%.sys + +@echo Copying the driver to the windows directory +@echo target file: %WINDIR%\%DIRVERFILE% +@copy %DIRVERFILE% %WINDIR%\%DIRVERFILE% + +@echo Remove a running service if needed... +@loaddrv stop %DIRVERNAME% >NUL +@if errorlevel 2 goto install + +@loaddrv remove %DIRVERNAME% >NUL +@if errorlevel 1 goto install + +:install +@echo Installing Windows NT/2k/XP driver: %DIRVERNAME% + +@loaddrv install %DIRVERNAME% %WINDIR%\%DIRVERFILE% +@if errorlevel 3 goto error + +@loaddrv start %DIRVERNAME% +@if errorlevel 1 goto error + +@loaddrv starttype %DIRVERNAME% auto +@if errorlevel 1 goto error + +@echo Success +@goto exit + +:error +@echo ERROR: Installation of %DIRVERNAME% failed + +:exit + diff --git a/avrdude/windows/loaddrv.c b/avrdude/windows/loaddrv.c new file mode 100644 index 00000000..ca92a2a1 --- /dev/null +++ b/avrdude/windows/loaddrv.c @@ -0,0 +1,460 @@ +// loaddrv.c - Dynamic driver install/start/stop/remove +// based on Paula Tomlinson's LOADDRV program. +// She describes it in her May 1995 article in Windows/DOS Developer's +// Journal (now Windows Developer's Journal). +// Modified by Chris Liechti +// I removed the old/ugly dialog, it now accepts command line options and +// prints error messages with textual description from the OS. + +#include +#include +#include +#include +#include +#include "loaddrv.h" + +// globals +SC_HANDLE hSCMan = NULL; + +//get ext messages for windows error codes: +void DisplayErrorText(DWORD dwLastError) { + LPSTR MessageBuffer; + DWORD dwBufferLength; + + DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM; + + dwBufferLength = FormatMessageA( + dwFormatFlags, + NULL, // module to get message from (NULL == system) + dwLastError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language + (LPSTR) &MessageBuffer, + 0, + NULL + ); + if (dwBufferLength) { + // Output message + puts(MessageBuffer); + // Free the buffer allocated by the system. + LocalFree(MessageBuffer); + } +} + +int exists(char *filename) { + FILE * pFile; + pFile = fopen(filename, "r"); + return pFile != NULL; +} + +void usage(void) { + printf("USGAE: loaddrv command drivername [args...]\n\n" + "NT/2k/XP Driver and Service modification tool.\n" + "(C)2002 Chris Liechti \n\n" + "Suported commands:\n\n" + " install [fullpathforinstall]\n" + " Install new service. Loaded from given path. If path is not present,\n" + " the local directory is searched for a .sys file. If the service\n" + " already exists, it must be removed first.\n" + " start\n" + " Start service. It must be installed in advance.\n" + " stop\n" + " Stop service.\n" + " remove\n" + " Remove service. It must be stopped in advance.\n" + " status\n" + " Show status information about service.\n" + " starttype auto|manual|system|disable\n" + " Change startup type to the given type.\n" + ); +} + +int main(int argc, char *argv[]) { + DWORD status = 0; + int level = 0; + if (argc < 3) { + usage(); + exit(1); + } + LoadDriverInit(); + if (strcmp(argv[1], "start") == 0) { + printf("starting %s... ", argv[2]); + status = DriverStart(argv[2]); + if ( status != OKAY) { + printf("start failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "stop") == 0) { + printf("stoping %s... ", argv[2]); + status = DriverStop(argv[2]); + if ( status != OKAY) { + printf("stop failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "install") == 0) { + char path[MAX_PATH*2]; + if (argc<4) { + char cwd[MAX_PATH]; + getcwd(cwd, sizeof cwd); + sprintf(path, "%s\\%s.sys", cwd, argv[2]); + } else { + strncpy(path, argv[3], MAX_PATH); + } + if (exists(path)) { + printf("installing %s from %s... ", argv[2], path); + status = DriverInstall(path, argv[2]); + if ( status != OKAY) { + printf("install failed (status %ld):\n", status); + level = 2; + } else { + printf("ok.\n"); + } + } else { + printf("install failed, file not found: %s\n", path); + level = 1; + } + } else if (strcmp(argv[1], "remove") == 0) { + printf("removing %s... ", argv[2]); + status = DriverRemove(argv[2]); + if ( status != OKAY) { + printf("remove failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "status") == 0) { + printf("status of %s:\n", argv[2]); + status = DriverStatus(argv[2]); + if ( status != OKAY) { + printf("stat failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "starttype") == 0) { + if (argc < 4) { + printf("Error: need start type (string) as argument.\n"); + level = 2; + } else { + DWORD type = 0; + printf("set start type of %s to %s... ", argv[2], argv[3]); + if (strcmp(argv[1], "boot") == 0) { + type = SERVICE_BOOT_START; + } else if (strcmp(argv[3], "system") == 0) { + type = SERVICE_SYSTEM_START; + } else if (strcmp(argv[3], "auto") == 0) { + type = SERVICE_AUTO_START; + } else if (strcmp(argv[3], "manual") == 0) { + type = SERVICE_DEMAND_START; + } else if (strcmp(argv[3], "disabled") == 0) { + type = SERVICE_DISABLED; + } else { + printf("unknown type\n"); + level = 1; + } + if (level == 0) { + status = DriverStartType(argv[2], type); + if ( status != OKAY) { + printf("set start type failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } + } + } else { + usage(); + level = 1; + } + if (status) DisplayErrorText(status); + LoadDriverCleanup(); + exit(level); + return 0; +} + + +DWORD LoadDriverInit(void) { + // connect to local service control manager + if ((hSCMan = OpenSCManager(NULL, NULL, + SC_MANAGER_ALL_ACCESS)) == NULL) { + return -1; + } + return OKAY; +} + +void LoadDriverCleanup(void) { + if (hSCMan != NULL) CloseServiceHandle(hSCMan); +} + +/**-----------------------------------------------------**/ +DWORD DriverInstall(LPSTR lpPath, LPSTR lpDriver) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + // add to service control manager's database + if ((hService = CreateService(hSCMan, lpDriver, + lpDriver, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, lpPath, + NULL, NULL, NULL, NULL, NULL)) == NULL) + dwStatus = GetLastError(); + else CloseServiceHandle(hService); + + return dwStatus; +} // DriverInstall + +/**-----------------------------------------------------**/ +DWORD DriverStart(LPSTR lpDriver) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { + // start the driver + if (!StartService(hService, 0, NULL)) + dwStatus = GetLastError(); + } else dwStatus = GetLastError(); + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStart + +/**-----------------------------------------------------**/ +DWORD DriverStop(LPSTR lpDriver) +{ + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + SERVICE_STATUS serviceStatus; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { + // stop the driver + if (!ControlService(hService, SERVICE_CONTROL_STOP, + &serviceStatus)) + dwStatus = GetLastError(); + } else dwStatus = GetLastError(); + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStop + +/**-----------------------------------------------------**/ +DWORD DriverRemove(LPSTR lpDriver) +{ + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { // remove the driver + if (!DeleteService(hService)) + dwStatus = GetLastError(); + } else dwStatus = GetLastError(); + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverRemove + +/**-----------------------------------------------------**/ +////extensions by Lch +/**-----------------------------------------------------**/ +DWORD DriverStatus(LPSTR lpDriver) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + DWORD dwBytesNeeded; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { + LPQUERY_SERVICE_CONFIG lpqscBuf; + //~ LPSERVICE_DESCRIPTION lpqscBuf2; + // Allocate a buffer for the configuration information. + if ((lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc( + LPTR, 4096)) != NULL) + { + //~ if ((lpqscBuf2 = (LPSERVICE_DESCRIPTION) LocalAlloc( + //~ LPTR, 4096)) != NULL) + { + // Get the configuration information. + if (QueryServiceConfig( + hService, + lpqscBuf, + 4096, + &dwBytesNeeded) //&& + //~ QueryServiceConfig2( + //~ hService, + //~ SERVICE_CONFIG_DESCRIPTION, + //~ lpqscBuf2, + //~ 4096, + //~ &dwBytesNeeded + ) + { + // Print the configuration information. + printf("Type: [0x%02lx] ", lpqscBuf->dwServiceType); + switch (lpqscBuf->dwServiceType) { + case SERVICE_WIN32_OWN_PROCESS: + printf("The service runs in its own process."); + break; + case SERVICE_WIN32_SHARE_PROCESS: + printf("The service shares a process with other services."); + break; + case SERVICE_KERNEL_DRIVER: + printf("Kernel driver."); + break; + case SERVICE_FILE_SYSTEM_DRIVER: + printf("File system driver."); + break; + case SERVICE_INTERACTIVE_PROCESS: + printf("The service can interact with the desktop."); + break; + default: + printf("Unknown type."); + } + printf("\nStart Type: [0x%02lx] ", lpqscBuf->dwStartType); + switch (lpqscBuf->dwStartType) { + case SERVICE_BOOT_START: + printf("Boot"); + break; + case SERVICE_SYSTEM_START: + printf("System"); + break; + case SERVICE_AUTO_START: + printf("Automatic"); + break; + case SERVICE_DEMAND_START: + printf("Manual"); + break; + case SERVICE_DISABLED: + printf("Disabled"); + break; + default: + printf("Unknown."); + } + printf("\nError Control: [0x%02lx] ", lpqscBuf->dwErrorControl); + switch (lpqscBuf->dwErrorControl) { + case SERVICE_ERROR_IGNORE: + printf("IGNORE: Ignore."); + break; + case SERVICE_ERROR_NORMAL: + printf("NORMAL: Display a message box."); + break; + case SERVICE_ERROR_SEVERE: + printf("SEVERE: Restart with last-known-good config."); + break; + case SERVICE_ERROR_CRITICAL: + printf("CRITICAL: Restart w/ last-known-good config."); + break; + default: + printf("Unknown."); + } + printf("\nBinary path: %s\n", lpqscBuf->lpBinaryPathName); + + if (lpqscBuf->lpLoadOrderGroup != NULL) + printf("Load order grp: %s\n", lpqscBuf->lpLoadOrderGroup); + if (lpqscBuf->dwTagId != 0) + printf("Tag ID: %ld\n", lpqscBuf->dwTagId); + if (lpqscBuf->lpDependencies != NULL) + printf("Dependencies: %s\n", lpqscBuf->lpDependencies); + if (lpqscBuf->lpServiceStartName != NULL) + printf("Start Name: %s\n", lpqscBuf->lpServiceStartName); + //~ if (lpqscBuf2->lpDescription != NULL) + //~ printf("Description: %s\n", lpqscBuf2->lpDescription); + } + //~ LocalFree(lpqscBuf2); + } + LocalFree(lpqscBuf); + } else { + dwStatus = GetLastError(); + } + } else { + dwStatus = GetLastError(); + } + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStatus + +/**-----------------------------------------------------**/ +DWORD DriverStartType(LPSTR lpDriver, DWORD dwStartType) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + SC_LOCK sclLock; + LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf; + DWORD dwBytesNeeded; + + // Need to acquire database lock before reconfiguring. + sclLock = LockServiceDatabase(hSCMan); + + // If the database cannot be locked, report the details. + if (sclLock == NULL) { + // Exit if the database is not locked by another process. + if (GetLastError() == ERROR_SERVICE_DATABASE_LOCKED) { + + // Allocate a buffer to get details about the lock. + lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc( + LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256); + if (lpqslsBuf != NULL) { + // Get and print the lock status information. + if (QueryServiceLockStatus( + hSCMan, + lpqslsBuf, + sizeof(QUERY_SERVICE_LOCK_STATUS)+256, + &dwBytesNeeded) ) + { + if (lpqslsBuf->fIsLocked) { + printf("Locked by: %s, duration: %ld seconds\n", + lpqslsBuf->lpLockOwner, + lpqslsBuf->dwLockDuration + ); + } else { + printf("No longer locked\n"); + } + } + LocalFree(lpqslsBuf); + } + } + dwStatus = GetLastError(); + } else { + // The database is locked, so it is safe to make changes. + // Open a handle to the service. + hService = OpenService( + hSCMan, // SCManager database + lpDriver, // name of service + SERVICE_CHANGE_CONFIG + ); // need CHANGE access + if (hService != NULL) { + // Make the changes. + if (!ChangeServiceConfig( + hService, // handle of service + SERVICE_NO_CHANGE, // service type: no change + dwStartType, // change service start type + SERVICE_NO_CHANGE, // error control: no change + NULL, // binary path: no change + NULL, // load order group: no change + NULL, // tag ID: no change + NULL, // dependencies: no change + NULL, // account name: no change + NULL, // password: no change + NULL) ) // display name: no change + { + dwStatus = GetLastError(); + } + } + // Release the database lock. + UnlockServiceDatabase(sclLock); + } + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStartType diff --git a/avrdude/windows/loaddrv.h b/avrdude/windows/loaddrv.h new file mode 100644 index 00000000..d7d102b9 --- /dev/null +++ b/avrdude/windows/loaddrv.h @@ -0,0 +1,20 @@ +#ifndef LOADDRV_H +#define LOADDRV_H + +#include + +#define OKAY 0 +#define UNEXPECTED_ERROR 9999 + +//prototypes +DWORD LoadDriverInit(void); +void LoadDriverCleanup(void); +DWORD DriverInstall(LPSTR, LPSTR); +DWORD DriverStart(LPSTR); +DWORD DriverStop(LPSTR); +DWORD DriverRemove(LPSTR); +DWORD DriverStatus(LPSTR); +DWORD DriverStartType(LPSTR, DWORD); +#endif //LOADDRV_H + + diff --git a/avrdude/windows/remove_giveio.bat b/avrdude/windows/remove_giveio.bat new file mode 100755 index 00000000..024427db --- /dev/null +++ b/avrdude/windows/remove_giveio.bat @@ -0,0 +1,14 @@ +@set DIRVERNAME=giveio + +@loaddrv stop %DIRVERNAME% +@if errorlevel 2 goto error + +@loaddrv remove %DIRVERNAME% +@if errorlevel 1 goto error + +@goto exit + +:error +@echo ERROR: Deinstallation of %DIRVERNAME% failed + +:exit diff --git a/avrdude/windows/status_giveio.bat b/avrdude/windows/status_giveio.bat new file mode 100755 index 00000000..bc821474 --- /dev/null +++ b/avrdude/windows/status_giveio.bat @@ -0,0 +1,12 @@ +@set DIRVERNAME=giveio + +@loaddrv status %DIRVERNAME% +@if errorlevel 1 goto error + +@goto exit + +:error +@echo ERROR: Status querry for %DIRVERNAME% failed + +:exit + diff --git a/avrdude/wiring.c b/avrdude/wiring.c new file mode 100644 index 00000000..1b7236e4 --- /dev/null +++ b/avrdude/wiring.c @@ -0,0 +1,236 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2011 Brett Hagman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Wiring bootloaders + * + * http://wiring.org.co/ + * + * The Wiring bootloader uses a near-complete STK500v2 protocol. + * (Only ISP specific programming commands are not implemented + * e.g. chip erase). + * DTR and RTS signals are diddled to set the board into programming mode. + * + * Also includes an extended parameter to introduce a delay after opening + * to accommodate multi-layered programmers/bootloaders. If the extended + * parameter 'snooze' > 0, then no DTR/RTS toggle takes place, and + * AVRDUDE will wait that amount of time in milliseconds before syncing. + * + * Unfortunately, there is no way to easily chain private programmer data + * when we "inherit" programmer types as we have (stk500v2). Sooooo, a + * *cringe* global variable is used to store the snooze time. + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include + +#include "avrdude.h" +#include "pgm.h" +#include "stk500v2_private.h" +#include "stk500v2.h" +#include "serial.h" + +/* + * Private data for this programmer. + */ +struct wiringpdata +{ + /* + * We just have the single snooze integer to carry around for now. + */ + int snoozetime; +}; + + +/* wiringpdata is our private data */ +/* pdata is stk500v2's private data (inherited) */ + +#define WIRINGPDATA(x) ((struct wiringpdata *)(x)) + +#define STK500V2PDATA(pgm) ((struct pdata *)(pgm->cookie)) + + +static void wiring_setup(PROGRAMMER * pgm) +{ + void *mycookie; + + /* + * First, have STK500v2 backend allocate its own private data. + */ + stk500v2_setup(pgm); + + /* + * Now prepare our data + */ + if ((mycookie = malloc(sizeof(struct wiringpdata))) == 0) { + fprintf(stderr, + "%s: wiring_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(mycookie, 0, sizeof(struct wiringpdata)); + WIRINGPDATA(mycookie)->snoozetime = 0; + + /* + * Store our own cookie in a safe place for the time being. + */ + STK500V2PDATA(pgm)->chained_pdata = mycookie; +} + +static void wiring_teardown(PROGRAMMER * pgm) +{ + void *mycookie; + + mycookie = STK500V2PDATA(pgm)->chained_pdata; + + free(mycookie); + + stk500v2_teardown(pgm); +} + +static int wiring_parseextparms(PROGRAMMER * pgm, LISTID extparms) +{ + LNODEID ln; + const char *extended_param; + int rv = 0; + void *mycookie = STK500V2PDATA(pgm)->chained_pdata; + + for (ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if (strncmp(extended_param, "snooze=", strlen("snooze=")) == 0) { + int newsnooze; + if (sscanf(extended_param, "snooze=%i", &newsnooze) != 1 || + newsnooze < 0) { + fprintf(stderr, + "%s: wiring_parseextparms(): invalid snooze time '%s'\n", + progname, extended_param); + rv = -1; + continue; + } + if (verbose >= 2) { + fprintf(stderr, + "%s: wiring_parseextparms(): snooze time set to %d ms\n", + progname, newsnooze); + } + WIRINGPDATA(mycookie)->snoozetime = newsnooze; + + continue; + } + + fprintf(stderr, + "%s: wiring_parseextparms(): invalid extended parameter '%s'\n", + progname, extended_param); + rv = -1; + } + + return rv; +} + +static int wiring_open(PROGRAMMER * pgm, char * port) +{ + int timetosnooze; + void *mycookie = STK500V2PDATA(pgm)->chained_pdata; + + strcpy(pgm->port, port); + serial_open(port, pgm->baudrate ? pgm->baudrate: 115200, &pgm->fd); + + /* If we have a snoozetime, then we wait and do NOT toggle DTR/RTS */ + + if (WIRINGPDATA(mycookie)->snoozetime > 0) { + timetosnooze = WIRINGPDATA(mycookie)->snoozetime; + + if (verbose >= 2) { + fprintf(stderr, + "%s: wiring_open(): snoozing for %d ms\n", + progname, timetosnooze); + } + while (timetosnooze--) + usleep(1000); + if (verbose >= 2) { + fprintf(stderr, + "%s: wiring_open(): done snoozing\n", + progname); + } + + } else { + /* Perform Wiring programming mode RESET. */ + /* This effectively *releases* both DTR and RTS. */ + /* i.e. both DTR and RTS rise to a HIGH logic level */ + /* since they are active LOW signals. */ + + if (verbose >= 2) { + fprintf(stderr, + "%s: wiring_open(): releasing DTR/RTS\n", + progname); + } + + serial_set_dtr_rts(&pgm->fd, 0); + usleep(50*1000); + + /* After releasing for 50 milliseconds, DTR and RTS */ + /* are asserted (i.e. logic LOW) again. */ + + if (verbose >= 2) { + fprintf(stderr, + "%s: wiring_open(): asserting DTR/RTS\n", + progname); + } + + serial_set_dtr_rts(&pgm->fd, 1); + usleep(50*1000); + } + + /* drain any extraneous input */ + stk500v2_drain(pgm, 0); + + if (stk500v2_getsync(pgm) < 0) + return -1; + + return 0; +} + +static void wiring_close(PROGRAMMER * pgm) +{ + serial_set_dtr_rts(&pgm->fd, 0); + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + +void wiring_initpgm(PROGRAMMER * pgm) +{ + /* The Wiring bootloader uses a near-complete STK500v2 protocol. */ + + stk500v2_initpgm(pgm); + + strcpy(pgm->type, "Wiring"); + pgm->open = wiring_open; + pgm->close = wiring_close; + + pgm->setup = wiring_setup; + pgm->teardown = wiring_teardown; + pgm->parseextparams = wiring_parseextparms; +} + diff --git a/avrdude/wiring.h b/avrdude/wiring.h new file mode 100644 index 00000000..57f70a75 --- /dev/null +++ b/avrdude/wiring.h @@ -0,0 +1,29 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2011 Brett Hagman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef wiring_h__ +#define wiring_h__ + +void wiring_initpgm(PROGRAMMER * pgm); + +#endif + +