pax_global_header00006660000000000000000000000064137103730700014513gustar00rootroot0000000000000052 comment=51fd9dffc206d132614f30402b50cd712fa9a60c cc-tool-0.27/000077500000000000000000000000001371037307000130035ustar00rootroot00000000000000cc-tool-0.27/.gitignore000066400000000000000000000003461371037307000147760ustar00rootroot00000000000000*.o .dirstamp /cc-tool /Makefile /Makefile.in /aclocal.m4 /autom4te.cache /config.guess /config.log /config.report /config.status /config.sub /configure /missing /install-sh /libtool /ltmain.sh /compile /m4/libtool.m4 /m4/lt*.m4 cc-tool-0.27/AUTHORS000066400000000000000000000000411371037307000140460ustar00rootroot00000000000000George Stark george-u@yandex.com cc-tool-0.27/COPYING000066400000000000000000000431221371037307000140400ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. cc-tool-0.27/ChangeLog000066400000000000000000000024301371037307000145540ustar00rootroot0000000000000011/08/2011 version 0.11 * first public release, alpha version 11/10/2011 version 0.12 * fixed merge data sections bug * add operation log 11/12/2011 version 0.13 * lots of fixes, status changed to beta 01/11/2012 version 0.15 * fix compile time error on x64 machines * minor changes 03/12/2012 version 0.16 * fixed CC debugger device USB PID value 06/06/2012 version 0.18 * fixed wrong CC111x identification * added reference in linux man pages format 09/26/2012 version 0.20 * added CC2541 target signature * fixed mac addresses reading for CC254x and CC253x units * added options --write-mac-address and --preserve-mac-address * fixed lock bit writing * fixed mac address byte order 10/26/2012 version 0.22 * added support for SmartRF04EB V1.1 programmer board (experimental) * added command line option --flash-size * fixed mac address writing for CC243x 11/24/2012 version 0.24 * updated autoconf scripts to support Mac OS * lock type for --lock option now may be specified by string like like debug, boot etc * added support for CC2543, CC2544, CC2545 targets (experimental) * bug fixing 03/01/1013 version 0.26 * fixed bug with -d option * handle programmer devices those have no iProduct string descriptor Further changes are tracked in the project's Git history. cc-tool-0.27/Makefile.am000066400000000000000000000021211371037307000150330ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 man_MANS = man/cc-tool.1 AM_CPPFLAGS = $(LIBUSB_CFLAGS) $(BOOST_CPPFLAGS) -O3 -Isrc/programmer -Isrc/common -Isrc/usb -Isrc -Isrc/application AM_LDFLAGS = \ $(BOOST_FILESYSTEM_LDFLAGS) \ $(BOOST_REGEX_LDFLAGS) \ $(BOOST_SYSTEM_LDFLAGS) \ $(BOOST_PROGRAM_OPTIONS_LDFLAGS) # $(BOOST_THREADS_LDFLAGS) LDADD = $(LIBUSB_LIBS) \ $(BOOST_FILESYSTEM_LIBS) \ $(BOOST_REGEX_LIBS) \ $(BOOST_SYSTEM_LIBS) \ $(BOOST_PROGRAM_OPTIONS_LIBS) # $(BOOST_THREADS_LIBS) bin_PROGRAMS=cc-tool cc_tool_SOURCES=src/main.cpp src/application/cc_flasher.cpp src/application/cc_base.cpp \ src/common/log.cpp src/common/common.cpp src/common/timer.cpp \ src/usb/usb_device.cpp \ src/data/binary_file.cpp src/data/data_section.cpp src/data/data_section_store.cpp \ src/data/file.cpp src/data/hex_file.cpp src/data/read_target.cpp \ src/data/progress_watcher.cpp \ src/programmer/cc_253x_254x.cpp src/programmer/cc_251x_111x.cpp \ src/programmer/cc_243x.cpp src/programmer/cc_programmer.cpp \ src/programmer/cc_unit_driver.cpp src/programmer/cc_unit_info.cpp cc_tool_LDFLAGS=-s cc-tool-0.27/NEWS000066400000000000000000000000071371037307000134770ustar00rootroot00000000000000no newscc-tool-0.27/README000066400000000000000000000012461371037307000136660ustar00rootroot00000000000000#### cc-tool version 0.26+ cc-tool provides support for Texas Instruments CC Debugger #### Building from source, dependencies: Ubuntu: libusb-1.0-0-dev, libboost-all-dev, autoconf, libtool Fedora: boost-devel, libusb1-devel Mac OS 10.6.7, from ports: libusb boost pkgconfig Regenerate Autotools files first by running `./bootstrap` script. #### User guide: man cc-tool #### Additional: File udev/90-cc-debugger.rules cotains udev rules changing permissions for TI CC Debugger device and TI evolution boards so they can be used from non-privileged accounts. Copy it to /etc/udev/rules.d #### Support: If you found a bug try to reproduce it with command line option --log. cc-tool-0.27/bootstrap000077500000000000000000000000621371037307000147440ustar00rootroot00000000000000#!/bin/sh autoreconf --verbose --install --force cc-tool-0.27/configure.ac000066400000000000000000000010331371037307000152660ustar00rootroot00000000000000dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT(cc-tool, 0.26+, george-u@yandex.com) AM_INIT_AUTOMAKE([no-dependencies foreign subdir-objects]) AM_SILENT_RULES([yes]) AC_CONFIG_MACRO_DIR([m4]) AC_PROG_LIBTOOL AC_PROG_CXX BOOST_REQUIRE([1.39]) BOOST_PROGRAM_OPTIONS([mt]) BOOST_SYSTEM([mt]) BOOST_REGEX([mt]) BOOST_FILESYSTEM([mt]) BOOST_FOREACH BOOST_SMART_PTR BOOST_STRING_ALGO BOOST_SIGNALS2 BOOST_CRC PKG_CHECK_MODULES([LIBUSB], [libusb-1.0 >= 1.0.0]) AC_CONFIG_FILES(Makefile) AC_OUTPUT cc-tool-0.27/docs/000077500000000000000000000000001371037307000137335ustar00rootroot00000000000000cc-tool-0.27/docs/chip table.odt000066400000000000000000000302111371037307000164330ustar00rootroot00000000000000PKǵwA^2 ''mimetypeapplication/vnd.oasis.opendocument.textPKǵwAConfigurations2/statusbar/PKǵwA'Configurations2/accelerator/current.xmlPKPKǵwAConfigurations2/floater/PKǵwAConfigurations2/popupmenu/PKǵwAConfigurations2/progressbar/PKǵwAConfigurations2/toolpanel/PKǵwAConfigurations2/menubar/PKǵwAConfigurations2/toolbar/PKǵwAConfigurations2/images/Bitmaps/PKǵwA content.xml]r}WU2%.ڧ.iOSؓe "! $%'˗fj&eM^܋{l6 :a%- Ț_~}OWg3 -W԰ҟնدl-kAdl Pk{}%=Ḷ nZe& {ںVi,%5>ignE;(_k;j^m;h4x`-IZuF:r[&tAZ|L6ZS褦`Ϫy#GIyU=yU=kwq&7Z}|cnQ9N=L_:12zpIv*Q| :1q-Q\1CQ9C%D4r|F9tHGɣ&xFEdX/8GG8Ǝ3K05ӝՆsGR8jN}:gWa?:P,d F I(i9=ihrҺ ﴤhg@5\}HT, ekn38Hn 4f&26ɏ~is}D>g H [3q-*@M`B [؀^&lj4BZ.G`vtx)gb:VnhSDl֟ - D w|@L- WFR@#+DH!h;Ȇ,nϛ7|c:(K4k'hXr_ODw%4@E+,{Cy70]9sdє-JmIVzU/hY o1̧о>8z53p@Ay0.I@CܖH?=iM H=Tzّޖt4eewt7&r ّޗi_$rjv?a}ER (KH.#J}-@vR?pG)lړz}x"j0vҢ8N&ߑu+)v?XIU @ArN=ŮlZ ѯ{fW0pшt Sfk4jw O7l 520z.&>-X_ \ҫٿo;}M~>}3kkHZ۹ϝɹSLM/{v8`{Vv>̻c$HHh3)I Zi_%ql#(`EwٚĞy z7dρlO,&,*}.;dqHOoS1a+-/~\[Wako=Q ;&0ΚcMBzzo{,#豯酴:4~^3)eN)f' u4{֊W0r0;{FotButeGҔ/!]isɠbMt^}^u"_Kh/"/]YP434.[t{>AA'a,SxHX+BE_h?̚w nJfR n_{#ɠ9MV۬ wY*UKV ?gUUaN 0\K~yK(???)P M_ m,.M_Y'M@BXd3_Ml)/J { KS)p&Xs^ 'ƅIW'E*6^leiQ oLis,jJn2B QzT5ʆU *B{!BPz!Qf;tBUe0njEDAZӟuM"G %E?SBWKF?+Pdg#J@;g se}g;5uMČQ2ڻ&f:< iVJ\^ib<]Np;*K9Qtw57Q9P7/a "HZ0:N/bC #8W9ǔW^2(buRV˷θF=t4~,5q`)$ՙ $Q8$$IRFxBԣ H*oP,_hy)ۨdyL-"NBn ArpSBTyJ %Tp>9odTIRM⛤jx5vݲ_[,s!E__-[ox yA!T75HѠlZh>7x98( o6}!9}ߟ M*C"$Twnn>'Eܟ+?ʅ077-.s99s,Z՚gnw{N_n9ZVrJڒPKHo ՜PKǵwA manifest.rdf͓n0D|e`9\_X/.%}]'*͡]fh8C;4`kg*|>y&ڸ^jj~ *!eI^eYExE%yL,Ƽ FD>} fy%N:90;:PD LچL(-&)}܂Gm-c1su_5R`""?^v}㧓 Fz{ ?VG5'PK=PKǵwA styles.xml[KWZ$7ٖe;,]`f7A&H. Z-H@R~̯O%ZluaŪ,?l\FA4Lc^G8 ~l"1',.sLe(>b"(93$Sc1Is{2#ZXٝ-Nxe5;;hwL+wNdኅ1 $IK]FEJYGv; _l6Z+Ji$ (F#˛cx]h/1 ȫbu4qẋK.qH>Qs <ﻖ=*mv3jUZx|?2I-'s=>,g4F S͕ѝFZULJeuZ5O/+s7T@7o8?4S0S'G[W 8LpLB[>Ox(Z#N`9dsPۜf4O !`ʹze :uK!f AhRH=!.01+?c ]_ *VtT2CpKZJ%|Xj3XSSҖY~5hyX $,)"J` .:13ZV4i)Ld&UC.1[M"um{jMFT\g|v *BsDhN6'GLE)dra7ʒq*Ce*ߺpٶ8E(T]`4< gH$yԃjX%Nbwn.BU _a%K>յq(:YG]D’INxzgieSl\( nU&yRb^JRGg(E.-1jwto{?6CNnD nFmt}A0?}nnhu)BSt`/p9ٱ_15:gmYg9gMjzXoo&ZI__m_f57ޢmdʋ{-gvN_T*"#kȮKz3RHڇςEЂsrd–dYr`\fr^M9r9.T\b%mut_,;ێYc&J%-3+yOxzףw#tֱR# ~3Ř *vjPe_5kKb" -+z^mT ~lp7gî*cS[a3^eRWҲ7{j=11w7C~a؁k`pc?u`?~0u`ؠTՠ(;\ Gd%~c!Iįi4-ye>zYGMO%Asaj2IZ Z{pRQaj#iʖ$;(>&vҔ'* '` l1*pp 0ow+JnTdiBsav궬6b Dx`?>POLw ^U&884֞ 2011-11-07T14:41:142012-11-24T02:46:14PT18H54M16S23OpenOffice.org/3.4.1$Linux OpenOffice.org_project/341m1$Build-9593PKǵwAThumbnails/thumbnail.pngV[XFE#MQq4sA[%\#pĥJr-\brmQ-wFq+ mqIros{s8;ɂw,I@B@l-vB>M\SܱnPV_9?ځs&Ylii07.GIό@3II-1 jivmk)Y .f;WC)1 |I OW:[S)"bRTKt(˜ `ydJ`<7yUg]iCV3?rd'iiUhQ sAio!Ҳa ȍqv-& i|d|AÊקO]jSȪ9=nK_[&nj_]|5ڷ(imkb,+#/ߊcƄD9 SF ZWIU=O apLe՜zT? uwyQȩ @J Smy~b!?EJ8)`gzt ;b^Equ(2[&&of>fFuV;FC"hRI]ZHr$ n؄`#MSZҰmRlYw=O.:.}V48 Bo9 1uY%x~]Ɵ]`š*StзdԺ6kW~FQ?cd~A8\,whܰ9=y͠G`ä ī*{*$=}a Τo۹+z#.YYgŐ7𝨸[Rg|{h;{ > y91ѐ`*c9U{#G?HES UA[k_"/[cWωkn'?T]D6sM*hZ˃Sicvm1َˇկxNx~ٰ<]abwJ푎?-+[)N\씑1}R ȍ|1ٳ?y5EެY5/2*V267pг'Sn<8=md̜>9c@0hDzRH0+KZ7> y-ŭwK-&m&˃iO_bM\=.j3Q*몞?Bز W!2\ol5< .JPľE;j9OH8t-)b2Q0?򫐺uc;ƘJsKԁgꊭAa h|v so 9P^ր6hQG+m&PKro PKǵwA settings.xmlZQs8 ~_;޶eZv]vIX)ONׅeC4%K>}{yWPjg C.gӸS>71H"ZOhԍ(@nHn1ͶՍTYd)|čjuX.OQͪjv4@9CUe߫B7EvCvTY좚희5uZAS"뛓c{[T6^9,޼uZ+`c kTw%.S@3]djUpEU;fjG`2v}p,D)V.ݯnc18~ư4ϊ}I<@'bAٳ;A Ҍ\ӈt8etgt҆.tIӕI4IG| zJOѕaV/Ö`EYLpʎ|)ѤS='|32/5=%y"QS[pAmqTF-$_X&2@;,9 \jR6=цOW637&&Z ؋6,KUE.V-{/}(AyeU0v]cw gwd0*?#7RsCoՂ`m=A/3*#s[N43l'{ VKM[q%+eRWؑWv8j89PbÀ0b J2yLfA27-7f-c妐ۂǾ~ BhU:bqu,v&]lcm{.Dq*D?P$6B j?He=E-n3n+{\;CP귂[:B QXj^ # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Additional permission under section 7 of the GNU General Public # License, version 3 ("GPLv3"): # # If you convey this file as part of a work that contains a # configuration script generated by Autoconf, you may do so under # terms of your choice. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . m4_define([_BOOST_SERIAL], [m4_translit([ # serial 25 ], [# ], [])]) # Original sources can be found at http://github.com/tsuna/boost.m4 # You can fetch the latest version of the script by doing: # wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 # ------ # # README # # ------ # # This file provides several macros to use the various Boost libraries. # The first macro is BOOST_REQUIRE. It will simply check if it's possible to # find the Boost headers of a given (optional) minimum version and it will # define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to # your configure so that users can specify non standard locations. # If the user's environment contains BOOST_ROOT and --with-boost was not # specified, --with-boost=$BOOST_ROOT is implicitly used. # For more README and documentation, go to http://github.com/tsuna/boost.m4 # Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, # simply read the README, it will show you what to do step by step. m4_pattern_forbid([^_?(BOOST|Boost)_]) # _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------- # Same as AC_EGREP_CPP, but leave the result in conftest.i. # # SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded # in double-quotes, so escape your double quotes. # # It could be useful to turn this into a macro which extracts the # value of any macro. m4_define([_BOOST_SED_CPP], [AC_LANG_PUSH([C++])dnl AC_LANG_PREPROC_REQUIRE()dnl AC_REQUIRE([AC_PROG_SED])dnl AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) AS_IF([dnl eval is necessary to expand ac_cpp. dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. dnl Beware of Windows end-of-lines, for instance if we are running dnl some Windows programs under Wine. In that case, boost/version.hpp dnl is certainly using "\r\n", but the regular Unix shell will only dnl strip `\n' with backquotes, not the `\r'. This results in dnl boost_cv_lib_version='1_37\r' for instance, which breaks dnl everything else. dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK dnl dnl Beware that GCC 5, when expanding macros, may embed # line directives dnl a within single line: dnl dnl # 1 "conftest.cc" dnl # 1 "" dnl # 1 "" dnl # 1 "conftest.cc" dnl # 1 "/opt/local/include/boost/version.hpp" 1 3 dnl # 2 "conftest.cc" 2 dnl boost-lib-version = dnl # 2 "conftest.cc" 3 dnl "1_56" dnl dnl So get rid of the # lines, and glue the remaining ones together. (eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | grep -v '#' | tr -d '\r' | tr -s '\n' ' ' | $SED -n -e "$1" >conftest.i 2>&1], [$3], [$4]) rm -rf conftest* AC_LANG_POP([C++])dnl ])# _BOOST_SED_CPP # BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) # ----------------------------------------------- # Look for Boost. If version is given, it must either be a literal of the form # "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a # variable "$var". # Defines the value BOOST_CPPFLAGS. This macro only checks for headers with # the required version, it does not check for any of the Boost libraries. # On # success, defines HAVE_BOOST. On failure, calls the optional # ACTION-IF-NOT-FOUND action if one was supplied. # Otherwise aborts with an error message. AC_DEFUN_ONCE([BOOST_REQUIRE], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_PROG_GREP])dnl echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD boost_save_IFS=$IFS boost_version_req=$1 IFS=. set x $boost_version_req 0 0 0 IFS=$boost_save_IFS shift boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` boost_version_req_string=$[1].$[2].$[3] AC_ARG_WITH([boost], [AS_HELP_STRING([--with-boost=DIR], [prefix of Boost $1 @<:@guess@:>@])])dnl AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl # If BOOST_ROOT is set and the user has not provided a value to # --with-boost, then treat BOOST_ROOT as if it the user supplied it. if test x"$BOOST_ROOT" != x; then if test x"$with_boost" = x; then AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) with_boost=$BOOST_ROOT else AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) fi fi AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl boost_save_CPPFLAGS=$CPPFLAGS AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], [boost_cv_inc_path], [boost_cv_inc_path=no AC_LANG_PUSH([C++])dnl m4_pattern_allow([^BOOST_VERSION$])dnl AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include #if !defined BOOST_VERSION # error BOOST_VERSION is not defined #elif BOOST_VERSION < $boost_version_req # error Boost headers version < $boost_version_req #endif ]])]) # If the user provided a value to --with-boost, use it and only it. case $with_boost in #( ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ /usr/include C:/Boost/include;; #( *) set x "$with_boost/include" "$with_boost";; esac shift for boost_dir do # Without --layout=system, Boost (or at least some versions) installs # itself in /include/boost-. This inner loop helps to # find headers in such directories. # # Any ${boost_dir}/boost-x_xx directories are searched in reverse version # order followed by ${boost_dir}. The final '.' is a sentinel for # searching $boost_dir" itself. Entries are whitespace separated. # # I didn't indent this loop on purpose (to avoid over-indented code) boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ && echo .` for boost_inc in $boost_layout_system_search_list do if test x"$boost_inc" != x.; then boost_inc="$boost_dir/$boost_inc" else boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list fi if test x"$boost_inc" != x; then # We are going to check whether the version of Boost installed # in $boost_inc is usable by running a compilation that # #includes it. But if we pass a -I/some/path in which Boost # is not installed, the compiler will just skip this -I and # use other locations (either from CPPFLAGS, or from its list # of system include directories). As a result we would use # header installed on the machine instead of the /some/path # specified by the user. So in that precise case (trying # $boost_inc), make sure the version.hpp exists. # # Use test -e as there can be symlinks. test -e "$boost_inc/boost/version.hpp" || continue CPPFLAGS="$CPPFLAGS -I$boost_inc" fi AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) if test x"$boost_cv_inc_path" = xyes; then if test x"$boost_inc" != x; then boost_cv_inc_path=$boost_inc fi break 2 fi done done AC_LANG_POP([C++])dnl ]) case $boost_cv_inc_path in #( no) boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], [AC_MSG_NOTICE([$boost_errmsg])]) $2 ;;#( yes) BOOST_CPPFLAGS= ;;#( *) AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl ;; esac if test x"$boost_cv_inc_path" != xno; then AC_DEFINE([HAVE_BOOST], [1], [Defined if the requested minimum BOOST version is satisfied]) AC_CACHE_CHECK([for Boost's header version], [boost_cv_lib_version], [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], [#include boost-lib-version = BOOST_LIB_VERSION], [boost_cv_lib_version=`cat conftest.i`])]) # e.g. "134" for 1_34_1 or "135" for 1_35 boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` case $boost_major_version in #( '' | *[[!0-9]]*) AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version']) ;; esac fi CPPFLAGS=$boost_save_CPPFLAGS ])# BOOST_REQUIRE # BOOST_STATIC() # -------------- # Add the "--enable-static-boost" configure argument. If this argument is given # on the command line, static versions of the libraries will be looked up. AC_DEFUN([BOOST_STATIC], [AC_ARG_ENABLE([static-boost], [AS_HELP_STRING([--enable-static-boost], [Prefer the static boost libraries over the shared ones [no]])], [enable_static_boost=yes], [enable_static_boost=no])])# BOOST_STATIC # BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) # -------------------------------------------------------------------------- # Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for # some parts of the Boost library which are only made of headers and don't # require linking (such as Boost.Foreach). # # Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be # found in the first place, in which case by default a notice is issued to the # user. Presumably if we haven't died already it's because it's OK to not have # Boost, which is why only a notice is issued instead of a hard error. # # Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in # case of success # (where HEADER-NAME is written LIKE_THIS, e.g., # HAVE_BOOST_FOREACH_HPP). AC_DEFUN([BOOST_FIND_HEADER], [AC_REQUIRE([BOOST_REQUIRE])dnl if test x"$boost_cv_inc_path" = xno; then m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) else AC_LANG_PUSH([C++])dnl boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CHECK_HEADER([$1], [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [Define to 1 if you have <$1>])])], [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) CPPFLAGS=$boost_save_CPPFLAGS AC_LANG_POP([C++])dnl fi ])# BOOST_FIND_HEADER # BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Look for the Boost library COMPONENT-NAME (e.g., `thread', for # libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g., # "thread_win32 thread"). Check that HEADER-NAME works and check that # libboost_LIB-NAME can link with the code CXX-TEST. The optional # argument CXX-PROLOGUE can be used to include some C++ code before # the `main' function. # # Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). # # Boost libraries typically come compiled with several flavors (with different # runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one # or more of the following letters: sgdpn (in that order). s = static # runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, # n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' # must always be used along with `p'). Additionally, PREFERRED-RT-OPT can # start with `mt-' to indicate that there is a preference for multi-thread # builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp # ... If you want to make sure you have a specific version of Boost # (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. AC_DEFUN([BOOST_FIND_LIBS], [AC_REQUIRE([BOOST_REQUIRE])dnl AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl AC_REQUIRE([BOOST_STATIC])dnl AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl if test x"$boost_cv_inc_path" = xno; then AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) else dnl The else branch is huge and wasn't intended on purpose. AC_LANG_PUSH([C++])dnl AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl BOOST_FIND_HEADER([$4]) boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], [_BOOST_FIND_LIBS($@)]) case $Boost_lib in #( (no) _AC_MSG_LOG_CONFTEST AC_MSG_ERROR([cannot find the flags to link with Boost $1]) ;; esac AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl CPPFLAGS=$boost_save_CPPFLAGS AS_VAR_POPDEF([Boost_lib])dnl AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl AS_VAR_POPDEF([Boost_lib_LDPATH])dnl AS_VAR_POPDEF([Boost_lib_LIBS])dnl AC_LANG_POP([C++])dnl fi ]) # BOOST_FIND_LIB([LIB-NAME], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Backward compatibility wrapper for BOOST_FIND_LIBS. AC_DEFUN([BOOST_FIND_LIB], [BOOST_FIND_LIBS([$1], $@)]) # _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Real implementation of BOOST_FIND_LIBS: rely on these local macros: # Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS # # The algorithm is as follows: first look for a given library name # according to the user's PREFERRED-RT-OPT. For each library name, we # prefer to use the ones that carry the tag (toolset name). Each # library is searched through the various standard paths were Boost is # usually installed. If we can't find the standard variants, we try # to enforce -mt (for instance on MacOSX, libboost_thread.dylib # doesn't exist but there's -obviously- libboost_thread-mt.dylib). AC_DEFUN([_BOOST_FIND_LIBS], [Boost_lib=no case "$3" in #( (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #( (*) boost_mt=; boost_rtopt=$3;; esac if test $enable_static_boost = yes; then boost_rtopt="s$boost_rtopt" fi # Find the proper debug variant depending on what we've been asked to find. case $boost_rtopt in #( (*d*) boost_rt_d=$boost_rtopt;; #( (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( (*) boost_rt_d='-d';; esac # If the PREFERRED-RT-OPT are not empty, prepend a `-'. test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" $boost_guess_use_mt && boost_mt=-mt # Look for the abs path the static archive. # $libext is computed by Libtool but let's make sure it's non empty. test -z "$libext" && AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) boost_save_ac_objext=$ac_objext # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$4> $6], [$5])]) dnl Optimization hacks: compiling C++ is slow, especially with Boost. What dnl we're trying to do here is guess the right combination of link flags dnl (LIBS / LDFLAGS) to use a given library. This can take several dnl iterations before it succeeds and is thus *very* slow. So what we do dnl instead is that we compile the code first (and thus get an object file, dnl typically conftest.o). Then we try various combinations of link flags dnl until we succeed to link conftest.o in an executable. The problem is dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always dnl remove all the temporary files including conftest.o. So the trick here dnl is to temporarily change the value of ac_objext so that conftest.o is dnl preserved accross tests. This is obviously fragile and I will burn in dnl hell for not respecting Autoconf's documented interfaces, but in the dnl mean time, it optimizes the macro by a factor of 5 to 30. dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left dnl empty because the test file is generated only once above (before we dnl start the for loops). AC_COMPILE_IFELSE([], [ac_objext=do_not_rm_me_plz], [AC_MSG_ERROR([cannot compile a test that uses Boost $1])]) ac_objext=$boost_save_ac_objext boost_failed_libs= # Don't bother to ident the following nested for loops, only the 2 # innermost ones matter. for boost_lib_ in $2; do for boost_tag_ in -$boost_cv_lib_tag ''; do for boost_ver_ in -$boost_cv_lib_version ''; do for boost_mt_ in $boost_mt -mt ''; do for boost_rtopt_ in $boost_rtopt '' -d; do for boost_lib in \ boost_$boost_lib_$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_rtopt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_mt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_ver_ do # Avoid testing twice the same lib case $boost_failed_libs in #( (*@$boost_lib@*) continue;; esac # If with_boost is empty, we'll search in /lib first, which is not quite # right so instead we'll try to a location based on where the headers are. boost_tmp_lib=$with_boost test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} for boost_ldpath in "$boost_tmp_lib/lib" '' \ /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ "$with_boost" C:/Boost/lib /lib* do # Don't waste time with directories that don't exist. if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then continue fi boost_save_LDFLAGS=$LDFLAGS # Are we looking for a static library? case $boost_ldpath:$boost_rtopt_ in #( (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" test -e "$Boost_lib_LIBS" || continue;; #( (*) # No: use -lboost_foo to find the shared library. Boost_lib_LIBS="-l$boost_lib";; esac boost_save_LIBS=$LIBS LIBS="$Boost_lib_LIBS $LIBS" test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" dnl First argument of AC_LINK_IFELSE left empty because the test file is dnl generated only once above (before we start the for loops). _BOOST_AC_LINK_IFELSE([], [Boost_lib=yes], [Boost_lib=no]) ac_objext=$boost_save_ac_objext LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS if test x"$Boost_lib" = xyes; then # Check or used cached result of whether or not using -R or # -rpath makes sense. Some implementations of ld, such as for # Mac OSX, require -rpath but -R is the flag known to work on # other systems. https://github.com/tsuna/boost.m4/issues/19 AC_CACHE_VAL([boost_cv_rpath_link_ldflag], [case $boost_ldpath in '') # Nothing to do. boost_cv_rpath_link_ldflag= boost_rpath_link_ldflag_found=yes;; *) for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" LIBS="$Boost_lib_LIBS $boost_save_LIBS" _BOOST_AC_LINK_IFELSE([], [boost_rpath_link_ldflag_found=yes break], [boost_rpath_link_ldflag_found=no]) done ;; esac AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS ]) test x"$boost_ldpath" != x && Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" Boost_lib_LDPATH="$boost_ldpath" break 7 else boost_failed_libs="$boost_failed_libs@$boost_lib@" fi done done done done done done done # boost_lib_ rm -f conftest.$ac_objext ]) # --------------------------------------- # # Checks for the various Boost libraries. # # --------------------------------------- # # List of boost libraries: http://www.boost.org/libs/libraries.htm # The page http://beta.boost.org/doc/libs is useful: it gives the first release # version of each library (among other things). # BOOST_DEFUN(LIBRARY, CODE) # -------------------------- # Define BOOST_ as a macro that runs CODE. # # Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. m4_define([BOOST_DEFUN], [m4_indir([AC_DEFUN], m4_toupper([BOOST_$1]), [m4_pushdef([BOOST_Library], [$1])dnl $2 m4_popdef([BOOST_Library])dnl ]) ]) # BOOST_ARRAY() # ------------- # Look for Boost.Array BOOST_DEFUN([Array], [BOOST_FIND_HEADER([boost/array.hpp])]) # BOOST_ASIO() # ------------ # Look for Boost.Asio (new in Boost 1.35). BOOST_DEFUN([Asio], [AC_REQUIRE([BOOST_SYSTEM])dnl BOOST_FIND_HEADER([boost/asio.hpp])]) # BOOST_BIND() # ------------ # Look for Boost.Bind. BOOST_DEFUN([Bind], [BOOST_FIND_HEADER([boost/bind.hpp])]) # BOOST_CHRONO() # -------------- # Look for Boost.Chrono. BOOST_DEFUN([Chrono], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([chrono], [$1], [boost/chrono.hpp], [boost::chrono::thread_clock d;]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_CHRONO # BOOST_CONTEXT([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.51.0 BOOST_DEFUN([Context], [BOOST_FIND_LIB([context], [$1], [boost/context/all.hpp],[[ // creates a stack void * stack_pointer = new void*[4096]; std::size_t const size = sizeof(void*[4096]); // context fc uses f() as context function // fcontext_t is placed on top of context stack // a pointer to fcontext_t is returned fc = ctx::make_fcontext(stack_pointer, size, f); return ctx::jump_fcontext(&fcm, fc, 3) == 6;]],[dnl namespace ctx = boost::context; // context static ctx::fcontext_t fcm, *fc; // context-function static void f(intptr_t i) { ctx::jump_fcontext(fc, &fcm, i * 2); }]) ])# BOOST_CONTEXT # BOOST_CONVERSION() # ------------------ # Look for Boost.Conversion (cast / lexical_cast) BOOST_DEFUN([Conversion], [BOOST_FIND_HEADER([boost/cast.hpp]) BOOST_FIND_HEADER([boost/lexical_cast.hpp]) ])# BOOST_CONVERSION # BOOST_COROUTINE([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.53.0 BOOST_DEFUN([Coroutine], [ boost_coroutine_save_LIBS=$LIBS boost_coroutine_save_LDFLAGS=$LDFLAGS # Link-time dependency from coroutine to context BOOST_CONTEXT([$1]) # Starting from Boost 1.55 a dependency on Boost.System is added if test $boost_major_version -ge 155; then BOOST_SYSTEM([$1]) fi m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)]) LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS" BOOST_FIND_LIB([coroutine], [$1], [boost/coroutine/coroutine.hpp], [boost::coroutines::coroutine< int(int) > coro; coro.empty();]) # Link-time dependency from coroutine to context, existed only in 1.53, in 1.54 # coroutine doesn't use context from its headers but from its library. if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS" fi if test $enable_static_boost = yes && test $boost_major_version -ge 155; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS" fi LIBS=$boost_coroutine_save_LIBS LDFLAGS=$boost_coroutine_save_LDFLAGS ])# BOOST_COROUTINE # BOOST_CRC() # ----------- # Look for Boost.CRC BOOST_DEFUN([CRC], [BOOST_FIND_HEADER([boost/crc.hpp]) ])# BOOST_CRC # BOOST_DATE_TIME([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Date_Time], [BOOST_FIND_LIB([date_time], [$1], [boost/date_time/posix_time/posix_time.hpp], [boost::posix_time::ptime t;]) ])# BOOST_DATE_TIME # BOOST_FILESYSTEM([PREFERRED-RT-OPT]) # ------------------------------------ # Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. # Do not check for boost/filesystem.hpp because this file was introduced in # 1.34. BOOST_DEFUN([Filesystem], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([filesystem], [$1], [boost/filesystem/path.hpp], [boost::filesystem::path p;]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_FILESYSTEM # BOOST_FLYWEIGHT() # ----------------- # Look for Boost.Flyweight. BOOST_DEFUN([Flyweight], [dnl There's a hidden dependency on pthreads. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl BOOST_FIND_HEADER([boost/flyweight.hpp]) AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag]) ]) # BOOST_FOREACH() # --------------- # Look for Boost.Foreach. BOOST_DEFUN([Foreach], [BOOST_FIND_HEADER([boost/foreach.hpp])]) # BOOST_FORMAT() # -------------- # Look for Boost.Format. # Note: we can't check for boost/format/format_fwd.hpp because the header isn't # standalone. It can't be compiled because it triggers the following error: # boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' # does not name a type BOOST_DEFUN([Format], [BOOST_FIND_HEADER([boost/format.hpp])]) # BOOST_FUNCTION() # ---------------- # Look for Boost.Function BOOST_DEFUN([Function], [BOOST_FIND_HEADER([boost/function.hpp])]) # BOOST_GEOMETRY() # ---------------- # Look for Boost.Geometry (new since 1.47.0). BOOST_DEFUN([Geometry], [BOOST_FIND_HEADER([boost/geometry.hpp]) ])# BOOST_GEOMETRY # BOOST_GRAPH([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Graph], [BOOST_FIND_LIB([graph], [$1], [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) ])# BOOST_GRAPH # BOOST_IOSTREAMS([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([IOStreams], [BOOST_FIND_LIB([iostreams], [$1], [boost/iostreams/device/file_descriptor.hpp], [boost::iostreams::file_descriptor fd; fd.close();]) ])# BOOST_IOSTREAMS # BOOST_HASH() # ------------ # Look for Boost.Functional/Hash BOOST_DEFUN([Hash], [BOOST_FIND_HEADER([boost/functional/hash.hpp])]) # BOOST_LAMBDA() # -------------- # Look for Boost.Lambda BOOST_DEFUN([Lambda], [BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) # BOOST_LOCALE() # -------------- # Look for Boost.Locale BOOST_DEFUN([Locale], [BOOST_FIND_LIB([locale], [$1], [boost/locale.hpp], [[boost::locale::generator gen; std::locale::global(gen(""));]]) ])# BOOST_LOCALE # BOOST_LOG([PREFERRED-RT-OPT]) # ----------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log], [BOOST_FIND_LIB([log], [$1], [boost/log/core/core.hpp], [boost::log::attribute a; a.get_value();]) ])# BOOST_LOG # BOOST_LOG_SETUP([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log_Setup], [AC_REQUIRE([BOOST_LOG])dnl BOOST_FIND_LIB([log_setup], [$1], [boost/log/utility/setup/from_settings.hpp], [boost::log::basic_settings bs; bs.empty();]) ])# BOOST_LOG_SETUP # BOOST_MATH() # ------------ # Look for Boost.Math # TODO: This library isn't header-only but it comes in multiple different # flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, # libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, # libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the # right thing anyway. BOOST_DEFUN([Math], [BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) # BOOST_MPI([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is # set, otherwise tries CXX # BOOST_DEFUN([MPI], [boost_save_CXX=${CXX} boost_save_CXXCPP=${CXXCPP} if test x"${MPICXX}" != x; then CXX=${MPICXX} CXXCPP="${MPICXX} -E" fi BOOST_FIND_LIB([mpi], [$1], [boost/mpi.hpp], [int argc = 0; char **argv = 0; boost::mpi::environment env(argc,argv);]) CXX=${boost_save_CXX} CXXCPP=${boost_save_CXXCPP} ])# BOOST_MPI # BOOST_MULTIARRAY() # ------------------ # Look for Boost.MultiArray BOOST_DEFUN([MultiArray], [BOOST_FIND_HEADER([boost/multi_array.hpp])]) # BOOST_NUMERIC_UBLAS() # -------------------------- # Look for Boost.NumericUblas (Basic Linear Algebra) BOOST_DEFUN([Numeric_Ublas], [BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) ])# BOOST_NUMERIC_UBLAS # BOOST_NUMERIC_CONVERSION() # -------------------------- # Look for Boost.NumericConversion (policy-based numeric conversion) BOOST_DEFUN([Numeric_Conversion], [BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) ])# BOOST_NUMERIC_CONVERSION # BOOST_OPTIONAL() # ---------------- # Look for Boost.Optional BOOST_DEFUN([Optional], [BOOST_FIND_HEADER([boost/optional.hpp])]) # BOOST_PREPROCESSOR() # -------------------- # Look for Boost.Preprocessor BOOST_DEFUN([Preprocessor], [BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) # BOOST_RANGE() # -------------------- # Look for Boost.Range BOOST_DEFUN([Range], [BOOST_FIND_HEADER([boost/range/adaptors.hpp])]) # BOOST_UNORDERED() # ----------------- # Look for Boost.Unordered BOOST_DEFUN([Unordered], [BOOST_FIND_HEADER([boost/unordered_map.hpp])]) # BOOST_UUID() # ------------ # Look for Boost.Uuid BOOST_DEFUN([Uuid], [BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) # BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) # ----------------------------------------- # Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Program_Options], [BOOST_FIND_LIB([program_options], [$1], [boost/program_options.hpp], [boost::program_options::options_description d("test");]) ])# BOOST_PROGRAM_OPTIONS # _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) # ------------------------------------ # Save VARIABLE, and define it via `python-config --FLAG`. # Substitute BOOST_PYTHON_VARIABLE. m4_define([_BOOST_PYTHON_CONFIG], [AC_SUBST([BOOST_PYTHON_$1], [`python-config --$2 2>/dev/null`])dnl boost_python_save_$1=$$1 $1="$$1 $BOOST_PYTHON_$1"]) # BOOST_PYTHON([PREFERRED-RT-OPT]) # -------------------------------- # Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Python], [_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) _BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) _BOOST_PYTHON_CONFIG([LIBS], [libs]) m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl BOOST_FIND_LIBS([python], [python python3], [$1], [boost/python.hpp], [], [BOOST_PYTHON_MODULE(empty) {}]) CPPFLAGS=$boost_python_save_CPPFLAGS LDFLAGS=$boost_python_save_LDFLAGS LIBS=$boost_python_save_LIBS ])# BOOST_PYTHON # BOOST_REF() # ----------- # Look for Boost.Ref BOOST_DEFUN([Ref], [BOOST_FIND_HEADER([boost/ref.hpp])]) # BOOST_REGEX([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Regex], [BOOST_FIND_LIB([regex], [$1], [boost/regex.hpp], [boost::regex exp("*"); boost::regex_match("foo", exp);]) ])# BOOST_REGEX # BOOST_SERIALIZATION([PREFERRED-RT-OPT]) # --------------------------------------- # Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Serialization], [BOOST_FIND_LIB([serialization], [$1], [boost/archive/text_oarchive.hpp], [std::ostream* o = 0; // Cheap way to get an ostream... boost::archive::text_oarchive t(*o);]) ])# BOOST_SERIALIZATION # BOOST_SIGNALS([PREFERRED-RT-OPT]) # --------------------------------- # Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Signals], [BOOST_FIND_LIB([signals], [$1], [boost/signal.hpp], [boost::signal s;]) ])# BOOST_SIGNALS # BOOST_SIGNALS2() # ---------------- # Look for Boost.Signals2 (new since 1.39.0). BOOST_DEFUN([Signals2], [BOOST_FIND_HEADER([boost/signals2.hpp]) ])# BOOST_SIGNALS2 # BOOST_SMART_PTR() # ----------------- # Look for Boost.SmartPtr BOOST_DEFUN([Smart_Ptr], [BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) BOOST_FIND_HEADER([boost/shared_ptr.hpp]) ]) # BOOST_STATICASSERT() # -------------------- # Look for Boost.StaticAssert BOOST_DEFUN([StaticAssert], [BOOST_FIND_HEADER([boost/static_assert.hpp])]) # BOOST_STRING_ALGO() # ------------------- # Look for Boost.StringAlgo BOOST_DEFUN([String_Algo], [BOOST_FIND_HEADER([boost/algorithm/string.hpp]) ]) # BOOST_SYSTEM([PREFERRED-RT-OPT]) # -------------------------------- # Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.35.0. BOOST_DEFUN([System], [BOOST_FIND_LIB([system], [$1], [boost/system/error_code.hpp], [boost::system::error_code e; e.clear();]) ])# BOOST_SYSTEM # BOOST_TEST([PREFERRED-RT-OPT]) # ------------------------------ # Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Test], [m4_pattern_allow([^BOOST_CHECK$])dnl BOOST_FIND_LIB([unit_test_framework], [$1], [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], [using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; }]) ])# BOOST_TEST # BOOST_THREAD([PREFERRED-RT-OPT]) # --------------------------------- # Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Thread], [dnl Having the pthread flag is required at least on GCC3 where dnl boost/thread.hpp would complain if we try to compile without dnl -pthread on GNU/Linux. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl boost_thread_save_LIBS=$LIBS boost_thread_save_LDFLAGS=$LDFLAGS boost_thread_save_CPPFLAGS=$CPPFLAGS # Link-time dependency from thread to system was added as of 1.49.0. if test $boost_major_version -ge 149; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" # When compiling for the Windows platform, the threads library is named # differently. This suffix doesn't exist in new versions of Boost, or # possibly new versions of GCC on mingw I am assuming it's Boost's change for # now and I am setting version to 1.48, for lack of knowledge as to when this # change occurred. if test $boost_major_version -lt 148; then case $host_os in (*mingw*) boost_thread_lib_ext=_win32;; esac fi BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext], [$1], [boost/thread.hpp], [boost::thread t; boost::mutex m;]) case $host_os in (*mingw*) boost_thread_w32_socket_link=-lws2_32;; esac BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link" BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" LIBS=$boost_thread_save_LIBS LDFLAGS=$boost_thread_save_LDFLAGS CPPFLAGS=$boost_thread_save_CPPFLAGS ])# BOOST_THREAD AU_ALIAS([BOOST_THREADS], [BOOST_THREAD]) # BOOST_TOKENIZER() # ----------------- # Look for Boost.Tokenizer BOOST_DEFUN([Tokenizer], [BOOST_FIND_HEADER([boost/tokenizer.hpp])]) # BOOST_TRIBOOL() # --------------- # Look for Boost.Tribool BOOST_DEFUN([Tribool], [BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) BOOST_FIND_HEADER([boost/logic/tribool.hpp]) ]) # BOOST_TUPLE() # ------------- # Look for Boost.Tuple BOOST_DEFUN([Tuple], [BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) # BOOST_TYPETRAITS() # -------------------- # Look for Boost.TypeTraits BOOST_DEFUN([TypeTraits], [BOOST_FIND_HEADER([boost/type_traits.hpp])]) # BOOST_UTILITY() # --------------- # Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, # etc.) BOOST_DEFUN([Utility], [BOOST_FIND_HEADER([boost/utility.hpp])]) # BOOST_VARIANT() # --------------- # Look for Boost.Variant. BOOST_DEFUN([Variant], [BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) BOOST_FIND_HEADER([boost/variant.hpp])]) # BOOST_POINTER_CONTAINER() # ------------------------ # Look for Boost.PointerContainer BOOST_DEFUN([Pointer_Container], [BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) ])# BOOST_POINTER_CONTAINER # BOOST_WAVE([PREFERRED-RT-OPT]) # ------------------------------ # NOTE: If you intend to use Wave/Spirit with thread support, make sure you # call BOOST_THREAD first. # Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Wave], [AC_REQUIRE([BOOST_FILESYSTEM])dnl AC_REQUIRE([BOOST_DATE_TIME])dnl boost_wave_save_LIBS=$LIBS boost_wave_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ $BOOST_THREAD_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ $BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" BOOST_FIND_LIB([wave], [$1], [boost/wave.hpp], [boost::wave::token_id id; get_token_name(id);]) LIBS=$boost_wave_save_LIBS LDFLAGS=$boost_wave_save_LDFLAGS ])# BOOST_WAVE # BOOST_XPRESSIVE() # ----------------- # Look for Boost.Xpressive (new since 1.36.0). BOOST_DEFUN([Xpressive], [BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) # ----------------- # # Internal helpers. # # ----------------- # # _BOOST_PTHREAD_FLAG() # --------------------- # Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag # which must be used in CPPFLAGS and LIBS. # # Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, # boost/thread.hpp will trigger a #error if -pthread isn't used: # boost/config/requires_threads.hpp:47:5: #error "Compiler threading support # is not turned on. Please set the correct command line options for # threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" # # Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html AC_DEFUN([_BOOST_PTHREAD_FLAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_LANG_PUSH([C++])dnl AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], [ boost_cv_pthread_flag= # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # (none): in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -lpthreads: AIX (must check this before -lpthread) # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) # -pthreads: Solaris/GCC # -mthreads: MinGW32/GCC, Lynx/GCC # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # -lpthread: GNU Linux, etc. # --thread-safe: KAI C++ case $host_os in #( *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( *) boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ -pthreads -mthreads -lpthread --thread-safe -mt";; esac # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) for boost_pthread_flag in '' $boost_pthread_flags; do boost_pthread_ok=false dnl Re-use the test file already generated. boost_pthreads__save_LIBS=$LIBS LIBS="$LIBS $boost_pthread_flag" AC_LINK_IFELSE([], [if grep ".*$boost_pthread_flag" conftest.err; then echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD else boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag fi]) LIBS=$boost_pthreads__save_LIBS $boost_pthread_ok && break done ]) AC_LANG_POP([C++])dnl ])# _BOOST_PTHREAD_FLAG # _BOOST_gcc_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_gcc_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl # _BOOST_mingw_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_mingw_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \ (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl # _BOOST_FIND_COMPILER_TAG() # -------------------------- # Internal. When Boost is installed without --layout=system, each library # filename will hold a suffix that encodes the compiler used during the # build. The Boost build system seems to call this a `tag'. AC_DEFUN([_BOOST_FIND_COMPILER_TAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], [boost_cv_lib_tag=unknown if test x$boost_cv_inc_path != xno; then AC_LANG_PUSH([C++])dnl # The following tests are mostly inspired by boost/config/auto_link.hpp # The list is sorted to most recent/common to oldest compiler (in order # to increase the likelihood of finding the right compiler with the # least number of compilation attempt). # Beware that some tests are sensible to the order (for instance, we must # look for MinGW before looking for GCC3). # I used one compilation test per compiler with a #error to recognize # each compiler so that it works even when cross-compiling (let me know # if you know a better approach). # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): # como, edg, kcc, bck, mp, sw, tru, xlc # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines # the same defines as GCC's). for i in \ _BOOST_mingw_test(5, 2) \ _BOOST_gcc_test(5, 2) \ _BOOST_mingw_test(5, 1) \ _BOOST_gcc_test(5, 1) \ _BOOST_mingw_test(5, 0) \ _BOOST_gcc_test(5, 0) \ _BOOST_mingw_test(4, 10) \ _BOOST_gcc_test(4, 10) \ _BOOST_mingw_test(4, 9) \ _BOOST_gcc_test(4, 9) \ _BOOST_mingw_test(4, 8) \ _BOOST_gcc_test(4, 8) \ _BOOST_mingw_test(4, 7) \ _BOOST_gcc_test(4, 7) \ _BOOST_mingw_test(4, 6) \ _BOOST_gcc_test(4, 6) \ _BOOST_mingw_test(4, 5) \ _BOOST_gcc_test(4, 5) \ _BOOST_mingw_test(4, 4) \ _BOOST_gcc_test(4, 4) \ _BOOST_mingw_test(4, 3) \ _BOOST_gcc_test(4, 3) \ _BOOST_mingw_test(4, 2) \ _BOOST_gcc_test(4, 2) \ _BOOST_mingw_test(4, 1) \ _BOOST_gcc_test(4, 1) \ _BOOST_mingw_test(4, 0) \ _BOOST_gcc_test(4, 0) \ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ _BOOST_gcc_test(3, 4) \ _BOOST_gcc_test(3, 3) \ "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ _BOOST_gcc_test(3, 2) \ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ _BOOST_gcc_test(3, 1) \ _BOOST_gcc_test(3, 0) \ "defined __BORLANDC__ @ bcb" \ "defined __ICC && (defined __unix || defined __unix__) @ il" \ "defined __ICL @ iw" \ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ _BOOST_gcc_test(2, 95) \ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" do boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if $boost_tag_test /* OK */ #else # error $boost_tag_test #endif ]])], [boost_cv_lib_tag=$boost_tag; break], []) done AC_LANG_POP([C++])dnl case $boost_cv_lib_tag in #( # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed # to "gcc41" for instance. *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. gcc*) boost_tag_x= case $host_os in #( darwin*) if test $boost_major_version -ge 136; then # The `x' added in r46793 of Boost. boost_tag_x=x fi;; esac # We can specify multiple tags in this variable because it's used by # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" ;; #( unknown) AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) boost_cv_lib_tag= ;; esac fi])dnl end of AC_CACHE_CHECK ])# _BOOST_FIND_COMPILER_TAG # _BOOST_GUESS_WHETHER_TO_USE_MT() # -------------------------------- # Compile a small test to try to guess whether we should favor MT (Multi # Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], [# Check whether we do better use `mt' even though we weren't ask to. AC_LANG_PUSH([C++])dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if defined _REENTRANT || defined _MT || defined __MT__ /* use -mt */ #else # error MT not needed #endif ]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) AC_LANG_POP([C++])dnl ]) # _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # ------------------------------------------------------------------- # Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, # will break when Autoconf changes its internals. Requires that you manually # rm -f conftest.$ac_objext in between to really different tests, otherwise # you will try to link a conftest.o left behind by a previous test. # Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this # macro). # # Don't use "break" in the actions, as it would short-circuit some code # this macro runs after the actions. m4_define([_BOOST_AC_LINK_IFELSE], [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl rm -f conftest$ac_exeext boost_save_ac_ext=$ac_ext boost_use_source=: # If we already have a .o, re-use it. We change $ac_ext so that $ac_link # tries to link the existing object file instead of compiling from source. test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) AS_IF([_AC_DO_STDERR($ac_link) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_executable_p conftest$ac_exeext dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. }], [$2], [if $boost_use_source; then _AC_MSG_LOG_CONFTEST fi $3]) ac_objext=$boost_save_ac_objext ac_ext=$boost_save_ac_ext dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), dnl as it would interfere with the next link command. rm -f core conftest.err conftest_ipa8_conftest.oo \ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl ])# _BOOST_AC_LINK_IFELSE # Local Variables: # mode: autoconf # End: cc-tool-0.27/man/000077500000000000000000000000001371037307000135565ustar00rootroot00000000000000cc-tool-0.27/man/cc-tool.1000066400000000000000000000127131371037307000152040ustar00rootroot00000000000000.\" Process this file with .\" groff -man -Tascii foo.1 .\" . .TH cc-tool 1 "March 01 2013" "cc-tool 0.26+" "USER COMMANDS" . .SH NAME cc-tool \- control Texas Instruments CC Debugger . .SH SYNOPSIS .B cc-tool [options] . .SH DESCRIPTION .B cc-tool provides support of Texas Instruments CC Debugger and several evaluation boards to program TI 8051-based System-On-Chip devices . .SH SUPPORTED DEVICES .B CC Debugger (VID: 0x0451 PID: 0x16a2) .br .B SmartRF04 Evaluation Board (VID: 0x11a0 PID: 0xdb20) .br .B SmartRF04 Evaluation Board (Chinese) (VID: 0x11a0 PID: 0xeb20) .br .B SmartRF05 Evaluation Board (VID: 0x0451 PID: 0x16a0) . .SH SUPPORTED TARGETS CC2540 CC2541 CC2543 CC2544 CC2545 CC2530 CC2531 CC2533 CC2430 CC2431 CC2510 CC2511 CC1110 CC1111 . .SH OPTIONS .TP .B \-h, \-\-help print help message . .TP .B \-d, \-\-device bus_number:device_number set programmer device usb address. The option should be used only if several CC Debugger devices connected to the system simultaneously. (you can use lsusb utility to enumerate devices connected to the system) . .TP .B \-f, \-\-fast set fast debug interface speed (by default: slow) . .TP .B \-i, \-\-read-info-page [file_name] read target info page (if target supports any). If no file-name specified data will be send to standard output. . .TP .B \-r, \-\-read file_name read flash memory and save to the specified file . .TP .B \-a, \-\-read-mac-address read target's mac address(es) (if target supports any). . .TP .B \-b, \-\-write-mac-address xx:xx:xx:xx:xx:xx[:xx:xx] write target's secondary mac address (if target supports any). mac address should be specified in hex notation, MSB first. The length of the address must be 6 or 8 bytes depending on target. . .TP .B \-p, \-\-preserve-mac-address before erasing target (secondary) mac address is read out and will be written back after flash programming. . .TP .B \-e, \-\-erase erase flash memory completely and reset lock bits . .TP .B \-w, \-\-write file_name[,offset] write specified file into flash memory. Optional offset value (in decimal) is an absolute target flash address and supported only for binary files. Option .I --write may be specified several times to build composite flash image from several hex and/or binary files, apply binary patches etc. Files will be merged in the order they appear in the command line. . .TP .B \-v, \-\-verify [method] verify flash after writing. Method can be .I crc (default) or .I read. Method .I read means that after writing all modified flash content is read back and compared to input flash image. Method .I crc means that after writing is completed target is configured to calculate CRC-16 over own flash and send results back so it ca be compared to crc of the input flash image. Method crc is much faster against read out all flash data. . .TP .B \-t, \-\-test search for programmer and target and print various information of them. . .TP .B \-l, \-\-lock lock_data specify lock data as hex string or list of lock qualifiers. Hex data must be exactly 1 byte (2 hex digits) or 16 bytes (32 hex digits), LSB first, depending on target. Lock qualifiers correspond to lock bit of target (see target datasheet). Not all targets support all qualifiers. Qualifiers are: .RS 10 .I debug - debug lock bit .RE .RS 10 .I boot - boot lock bit (for targets CC111x, CC243x, CC251x) .RE .RS 10 .I pages[:n[,k[,x-y]]] - specify what pages to lock (starting with 0), if target support per-page lock. (for targets CC253x, CC254x) .RE .RS 10 .I flash[:a] - specify the size in KB of the upper flash area to lock if target support per-flash-area-size lock (for targets CC111x, CC243x, CC251x) .RE Qualifier list is delimited by semicolon (See example section). .TP .B \-\-log [log_file] create log file with all operations performed. Useful for debugging cc-tool itself. Warning: if write operations is performed log file will also contain the written image! . .TP .B \-\-reset perform target reset. There's no need to use this option along with others because reset is performed anyway when needed . .TP .B \-n, \-\-name target_name specify target name e.g. CC2530 etc. If specified target does not match detected one no further actions are performed. This option is not required. . .TP .B \-s, \-\-flash-size specify target flash size specify target flash size in kilobytes. This option is required for any actions with MAC address when target is CC2430 . .SH SUPPORTED FILE FORMATS Supported image file formats are Intel hex or binary. Format will be determined automatically by file extension (hex or bin) or my be specified explicitly by adding .I ,bin or .I ,hex after file name. See EXAMPLES section. . .SH EXAMPLES .TP Read entire flash into binary file image.xxx .B cc-tool -r image.xxx,bin .TP Erase flash, write intel hex file image.hex and verify flash using default method .B cc-tool -v -e -w image.hex .TP Merge file image.hex and patch.bin (at offset 80), write resulting image, verify flash using read method .B cc-tool -v read -w image.hex --write patch.bin,80 .TP Set debug lock bit .B cc-tool --lock debug .TP Set debug lock bit and lock pages 0,1,2,3,4 .B cc-tool --lock debug;pages:0-4 .TP Set debug lock bit, boot lock bit, and set lock size 8K .B cc-tool --lock debug;boot;flash:8 . .SH EXIT STATUS .B cc-tool returns a zero exist status if all action were performed successfully. Non zero is returned in case of failure. . .SH AUTHOR George Stark (george-u (at) yandex.com) . cc-tool-0.27/src/000077500000000000000000000000001371037307000135725ustar00rootroot00000000000000cc-tool-0.27/src/application/000077500000000000000000000000001371037307000160755ustar00rootroot00000000000000cc-tool-0.27/src/application/cc_base.cpp000066400000000000000000000157361371037307000201740ustar00rootroot00000000000000/* * cc_base.cpp * * Created on: Nov 30, 2011 * Author: st */ #include #include "common.h" #include "version.h" #include "log.h" #include "timer.h" #include "programmer/cc_programmer.h" #include "cc_base.h" //============================================================================== static bool extract_usb_address(const String &str, uint_t &bus, uint_t &device) { boost::cmatch what; boost::regex hex_regex("0x([\\da-fA-F]{1,4}):0x([\\da-fA-F]{1,4})"); if (boost::regex_match(str.c_str(), what, hex_regex)) { hexstring_to_number(what[1].str(), bus); hexstring_to_number(what[2].str(), device); return true; } boost::regex regex("([\\d]{1,3}):([\\d]{1,3})"); if (!boost::regex_match(str.c_str(), what, regex)) return false; string_to_number(what[1].str(), bus); string_to_number(what[2].str(), device); return true; } //============================================================================== static std::ostream& operator <<(std::ostream &os, const USB_DeviceID &o) { os << std::hex << std::setfill('0') << std::nouppercase; os << " VID: 0x" << std::setw(4) << o.vendor_id; os << " PID: 0x" << std::setw(4) << o.product_id; os << " Description: " << o.description; return os; } //============================================================================== static void init_log(int argc, char *argv[], String &log_file) { if (log_file.empty()) log_file = String(MODULE_NAME) + ".log"; log_get().set_log_file(log_file); log_info("main, %s %u.%u", MODULE_NAME, VERSION_MAJOR, VERSION_MINOR); String command_line; while (argc--) command_line += String(*argv++) + " "; log_info("main, command line: %s", command_line.c_str()); } //============================================================================== static void print_usage(const po::options_description &desc) { std::cout << MODULE_DESCRIPTION << "\n"; std::cout << " Version: " << VERSION_MAJOR << "." << VERSION_MINOR << "\n"; std::cout << "\n Command line options:\n"; std::cout << desc; } //============================================================================== void CC_Base::init_options(po::options_description &desc) { desc.add_options() ("help,h", "produce help message"); desc.add_options() ("log", po::value(&option_log_name_)->implicit_value(""), "create log of all operations"); desc.add_options() ("device,d", po::value(&option_device_address_), "set programmer device usb address 'bus:device'"); desc.add_options() ("fast,f", "set fast debug interface speed (by default: slow)"); desc.add_options() ("name,n", po::value(&option_unit_name_), "specify target name e.g. CC2530 etc."); desc.add_options() ("allow-overlapping-records", "allow overlapping records in hex files, the last one wins (by default: they are disallowed)"); } //============================================================================== void CC_Base::on_help(const po::options_description &desc) { print_usage(desc); std::cout << "\n Supported targets:\n "; StringVector targets = programmer_.supported_unit_names(); foreach (const String &item, targets) std::cout << item << " "; std::cout << "\n\n Supported programmers:\n"; USB_DeviceIDVector devices = programmer_.supported_devices(); foreach (const USB_DeviceID &item, devices) std::cout << item << "\n"; } //============================================================================== bool CC_Base::read_options(const po::options_description &desc, const po::variables_map &vm) { if (vm.count("help")) { on_help(desc); return false; } if (vm.count("device")) { uint_t bus = 0, device = 0; if (!extract_usb_address(option_device_address_, bus, device)) throw po::error("Bad device address format"); } option_fast_interface_speed_ = vm.count("fast") > 0; option_allow_overlapping_records_ = vm.count("allow-overlapping-records") > 0; return true; } //============================================================================== bool CC_Base::init_unit() { String unit_name; bool supported = false; programmer_.unit_status(unit_name, supported); if (unit_name.empty()) { std::cout << " No target detected" << "\n"; return false; } std::cout << " Target: " << unit_name << "\n"; if (!supported) { std::cout << " Target not supported" << "\n"; log_info("main, target not supported"); return false; } boost::to_upper(option_unit_name_); if (unit_name != option_unit_name_ && !option_unit_name_.empty()) { std::cout << "Specified target " << option_unit_name_ << " not found" << "\n"; return false; } if (!programmer_.unit_connect(unit_info_)) { std::cout << " Unable to communicate with target" << "\n"; return false; } return true; } //============================================================================== bool CC_Base::init_programmer() { CC_Programmer::OpenResult open_result = CC_Programmer::OR_OK; if (!option_device_address_.empty()) { uint_t bus = 0, device = 0; extract_usb_address(option_device_address_, bus, device); open_result = programmer_.open(bus, device); if (open_result == CC_Programmer::OR_NOT_SUPPORTED) std::cout << std::setfill('0') << " Device at " << std::setw(3) << bus << ":" << std::setw(3) << device << " not supported" << "\n"; } else open_result = programmer_.open(); if (open_result != CC_Programmer::OR_OK) { std::cout << " CC Debugger device not found" << "\n"; return false; } programmer_.set_debug_interface_speed(option_fast_interface_speed_? CC_Programmer::IS_FAST : CC_Programmer::IS_SLOW); CC_ProgrammerInfo info; programmer_.programmer_info(info); std::cout << " Programmer: " << info.name << "\n"; return true; } //============================================================================== bool CC_Base::execute(int argc, char *argv[]) { po::options_description desc; init_options(desc); try { po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (vm.count("log")) init_log(argc, argv, option_log_name_); if (!read_options(desc, vm)) return false; if (init_programmer() && init_unit()) { log_info("main, start task processing"); process_tasks(); log_info("main, finish task processing"); programmer_.unit_close(); return true; } } catch (std::runtime_error& e) // usb, file error { std::cout << " Error occurred"; if (strlen(e.what())) { std::cout << ": " << e.what(); log_info("%s", e.what()); } std::cout << "\n"; } catch (po::error& e) // command line error { std::cout << " Bad command line options"; if (strlen(e.what())) std::cout << " (" << e.what() << ")"; std::cout << "\n Try --help for more information\n"; } return false; } //============================================================================== void CC_Base::process_tasks() { } //============================================================================== CC_Base::CC_Base() : option_allow_overlapping_records_(false), option_fast_interface_speed_(false) { } cc-tool-0.27/src/application/cc_base.h000066400000000000000000000020021371037307000176170ustar00rootroot00000000000000/* * cc_base.h * * Created on: Nov 30, 2011 * Author: st */ #ifndef _CC_BASE_H_ #define _CC_BASE_H_ #include #include "data/binary_file.h" #include "data/hex_file.h" #include "data/read_target.h" #include "data/data_section_store.h" #include "programmer/cc_programmer.h" namespace po = boost::program_options; class CC_Base : boost::noncopyable { public: bool execute(int argc, char *argv[]); CC_Base(); protected: virtual void init_options(po::options_description &); /// @return false if application should exit virtual bool read_options(const po::options_description &, const po::variables_map &); virtual void process_tasks(); UnitInfo unit_info_; CC_Programmer programmer_; bool option_allow_overlapping_records_; private: void on_help(const po::options_description &); bool init_programmer(); bool init_unit(); bool option_fast_interface_speed_; String option_unit_name_; String option_device_address_; String option_log_name_; }; #endif // !_CC_BASE_H_ cc-tool-0.27/src/application/cc_flasher.cpp000066400000000000000000000424771371037307000207100ustar00rootroot00000000000000/* * cc_tool.cpp * * Created on: Aug 3, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "common.h" #include "version.h" #include "log.h" #include "timer.h" #include "programmer/cc_programmer.h" #include "cc_flasher.h" enum Task { T_RESET = 0x0001, T_ERASE = 0x0002, T_WRITE_FLASH = 0x0004, T_READ_FLASH = 0x0008, T_VERIFY = 0x0010, T_LOCK = 0x0020, T_READ_MAC = 0x0040, T_WRITE_MAC = 0x0080, T_PRESERVE_MAC = 0x0100, T_READ_INFO_PAGE= 0x0200, T_TEST = 0x0400, }; //============================================================================== static String mac_address_to_string(const ByteVector &mac) { ByteVector data(mac.size(), 0); std::reverse_copy(mac.begin(), mac.end(), data.begin()); return binary_to_hex(&data[0], data.size(), ":"); } //============================================================================== static bool extract_mac_address(const String &mac, size_t length, ByteVector &data) { String exp; for (size_t i = 0; i < length; i++) exp += "([\\da-fA-F]{2}):"; exp.erase(exp.end() - 1); boost::cmatch what; boost::regex regex(exp); if (!boost::regex_match(mac.c_str(), what, regex)) return false; for (size_t i = length; i > 0; i--) data.push_back(std::strtoul(what[i].str().c_str(), NULL, 16)); return true; } //============================================================================== static void print_hex_dump(const ByteVector &data) { size_t total_size = data.size(); size_t offset = 0; while (total_size) { size_t size = std::min(total_size, (size_t)40); std::cout << binary_to_hex(&data[offset], size, "") << "\n"; offset += size; total_size -= size; } } //============================================================================== static void load_flash_data(const OptionFileInfo &file_info, DataSectionStore §ion_store, bool allow_overlapping_records) { if (file_info.type == "hex") { DataSectionStore sections; hex_file_load(file_info.name, sections, false, allow_overlapping_records); section_store.add_sections(sections, true); size_t n = 0; log_info("main, loaded hex file %s", file_info.name.c_str()); foreach (const DataSection &item, section_store.sections()) log_info(" section %02u, address: %06Xh, size: %06Xh", n++, item.address, item.size()); } if (file_info.type == "bin") { ByteVector data; binary_file_load(file_info.name, data); DataSection section(file_info.offset, data); section_store.add_section(section, true); log_info("main, loaded bin file %s, size: %u", file_info.name.c_str(), data.size()); } } //============================================================================== static std::ostream& operator <<(std::ostream &os, const CC_ProgrammerInfo &o) { os << " Name: " << o.name << "\n"; os << " Debugger ID: " << o.debugger_id << "\n"; os << std::hex << std::setfill('0') << std::uppercase; os << " Version: 0x" << std::setw(4) << o.fw_version << "\n"; os << " Revision: 0x" << std::setw(4) << o.fw_revision << "\n"; os << std::dec; return os; } //============================================================================== static std::ostream& operator <<(std::ostream &os, const UnitInfo &o) { os << " Name: " << o.name << "\n"; os << std::hex << std::setfill('0') << std::uppercase; os << " Revision: 0x" << std::setw(2) << (uint_t)o.revision << "\n"; os << " Internal ID: 0x" << std::setw(2) << (uint_t)o.internal_ID << "\n"; os << " ID: 0x" << std::setw(4) << o.ID << "\n"; os << std::dec; os << " Flash size: "; if (!o.flash_size) os << "n/a" << "\n"; else os << o.flash_size << " KB" << "\n"; os << " Flash page size: " << o.flash_page_size << "\n"; os << " RAM size: "; if (!o.ram_size) os << "n/a" << "\n"; else os << o.ram_size << " KB" << "\n"; os << std::dec; return os; } //============================================================================== static void on_progress(size_t done_read, size_t total_read) { std::cout << " Progress: " << done_read * 100 / total_read << "%\r" << std::flush; } //============================================================================== static void print_result(bool result) { // clear out progress message std::cout << String(18, ' ') << "\r" << std::flush; if (result) std::cout << " Completed" << "\n"; else std::cout << " Failed" << "\n"; } //============================================================================== static void print_result(bool result, const Timer& timer) { // clear out progress message std::cout << String(18, ' ') << "\r" << std::flush; if (result) std::cout << " Completed (" << timer.elapsed_time() << ")" << "\n"; else std::cout << " Failed" << "\n"; } //============================================================================== void CC_Flasher::init_options(po::options_description &desc) { CC_Base::init_options(desc); desc.add_options() ("read-info-page,i", po::value(&option_info_page_)->implicit_value(""), "read info pages"); desc.add_options() ("read-mac-address,a", "read mac address(es)"); desc.add_options() ("write-mac-address,b", po::value(), "write (secondary) mac address"); desc.add_options() ("preserve-mac-address,p", "preserve (secondary) mac address across writing"); desc.add_options() ("read,r", po::value(), "read flash memory"); desc.add_options() ("erase,e", "erase flash memory"); desc.add_options() ("write,w", po::value(), "write flash memory."); desc.add_options() ("verify,v", po::value()->implicit_value(""), "verify flash after write, method '(r)ead' or '(c)cr' (used by default)"); desc.add_options() ("reset", "perform target reset"); desc.add_options() ("test,t", "search for programmer and target"); desc.add_options() ("lock,l", po::value(&option_lock_data_), "specify lock data in hex numbers or by string: debug[;pages:xx]"); desc.add_options() ("flash-size,s", po::value(&option_flash_size_), "specify target flash size in KB"); } //============================================================================== bool CC_Flasher::read_options(const po::options_description &desc, const po::variables_map &vm) { if (!CC_Base::read_options(desc, vm)) return false; if (vm.count("read-mac-address")) task_set_ |= T_READ_MAC; if (vm.count("preserve-mac-address")) task_set_ |= T_PRESERVE_MAC; if (vm.count("write-mac-address")) { task_set_ |= T_WRITE_MAC; String value = vm["write-mac-address"].as(); if (!extract_mac_address(value, 6, mac_addr_) && !extract_mac_address(value, 8, mac_addr_)) throw po::error("bad mac address format - " + value); if (task_set_ & T_PRESERVE_MAC) throw po::error("incompatible options write-mac-address and preserve-mac-address"); } if (vm.count("read-info-page")) { task_set_ |= T_READ_INFO_PAGE; info_page_read_target_.set_source(option_info_page_); } if (vm.count("verify")) { task_set_ |= T_VERIFY; String value = vm["verify"].as(); if (value == "r" || value == "read") verify_method_ = CC_Programmer::VM_BY_READ; else if ((value == "c" || value == "crc")) verify_method_ = CC_Programmer::VM_BY_CRC; else if (!value.empty()) throw po::error("invalid verify method - " + value); } if (vm.count("reset")) task_set_ |= T_RESET; if (vm.count("erase")) task_set_ |= T_ERASE; if (vm.count("test")) task_set_ |= T_TEST; if (vm.count("read")) { task_set_ |= T_READ_FLASH; flash_read_target_.set_source(vm["read"].as()); } if (vm.count("write")) { if (!(task_set_ & T_ERASE)) { std::cout << " Writing flash is not supported without erase" << "\n"; return false; } task_set_ |= T_WRITE_FLASH; StringVector list = vm["write"].as(); foreach (String &item, list) { OptionFileInfo file_info; option_extract_file_info(item, file_info, true); load_flash_data(file_info, flash_write_data_, option_allow_overlapping_records_); } } if (vm.count("lock")) task_set_ |= T_LOCK; if ((task_set_ & T_VERIFY) && !(task_set_ & T_WRITE_FLASH)) throw po::error("'verify' option is used without write"); if (!option_flash_size_.empty()) { char *error = NULL; if (strtoull(option_flash_size_.c_str(), &error, 10) == 0 || *error != '\0') throw po::error("invalid flash size value " + option_flash_size_); } return true; } //============================================================================== bool CC_Flasher::validate_mac_options() { if (!(unit_info_.flags & UnitInfo::SUPPORT_MAC_ADDRESS) && (task_set_ & (T_WRITE_MAC | T_READ_MAC | T_PRESERVE_MAC))) { std::cout << " Target does not support MAC address" << "\n"; return false; } if (target_locked_ && (task_set_ & T_PRESERVE_MAC)) { std::cout << " Target is locked. Unable to preserve mac address" << "\n"; return false; } if ((task_set_ & T_WRITE_MAC) && mac_addr_.size() != unit_info_.mac_address_size) { std::cout << " Wrong MAC address length specified, must be " << unit_info_.mac_address_size << "\n"; return false; } if (task_set_ & (T_WRITE_MAC | T_READ_MAC | T_PRESERVE_MAC) && !unit_info_.max_flash_size) { std::cout << " Mac address operations are disabled because " "target flash size is unavailable." << "\n"; std::cout << " See --flash-size option" << "\n"; return false; } return true; } //============================================================================== StringVector split_string(const String& input) { StringVector list; String s = boost::to_lower_copy(input); boost::split(list, s, boost::is_any_of(";")); StringVector::iterator it = list.begin(); while (it != list.end()) { boost::trim(*it); if (it->empty()) it = list.erase(it); else it++; } return list; } //============================================================================== bool CC_Flasher::validate_lock_options() { if (!(task_set_ & T_LOCK)) return true; if (!hex_to_binary(option_lock_data_, lock_data_, "")) { // check if conversion failed due to odd number of hex digits: bool hex_data = true; foreach(char c, option_lock_data_) if (!std::isxdigit(c)) hex_data = false; if (hex_data) { std::cout << " Incorrect lock data" << "\n"; return false; } try { programmer_.unit_convert_lock_data(split_string(option_lock_data_), lock_data_); std::cout << " Lock data: " << binary_to_hex(lock_data_, "") << "\n"; } catch (std::exception &e) { std::cout << " Error reading lock data: " << e.what() << "\n"; return false; } } if (lock_data_.size() != programmer_.unit_lock_data_size()) { std::cout << " Lock data size must be " << programmer_.unit_lock_data_size() << "B, provided: " << lock_data_.size() << "\n"; return false; } return true; } //============================================================================== bool CC_Flasher::validate_flash_size_options() { if (option_flash_size_.empty()) return true; if (unit_info_.flash_size) std::cout << " Specified flash size is ignored (read from target instead) " << "\n"; else { uint_t flash_size = 0; string_to_number(option_flash_size_, flash_size); bool found = std::find( unit_info_.flash_sizes.begin(), unit_info_.flash_sizes.end(), flash_size) != unit_info_.flash_sizes.end(); if (!found) { String list; foreach (uint_t size, unit_info_.flash_sizes) string_append(list, number_to_string(size), ", "); std::cout << " Specified flash size is wrong"; if (list.size()) std::cout << "; valid values are " << list; std::cout << "\n"; return false; } programmer_.unit_set_flash_size(flash_size); } return true; } //============================================================================== void CC_Flasher::task_write_config() { String status; if (task_set_ & T_LOCK) status += " lock data"; if (task_set_ & T_WRITE_MAC) { if (!status.empty()) status += ", "; status += " mac address"; } std::cout << " Writing " << status << "..." << "\n"; print_result(programmer_.unit_config_write(mac_addr_, lock_data_)); } //============================================================================== void CC_Flasher::process_tasks() { if (!task_set_) { std::cout << " No actions specified" << "\n"; return; } if (!validate_lock_options()) return; target_locked_ = programmer_.unit_locked(); if (target_locked_) std::cout << " Target is locked." << "\n"; if (task_set_ & T_TEST) task_test(); if (target_locked_ && !(task_set_ & T_ERASE)) { std::cout << " No operations allowed on locked target without erasing\n"; return; } if (target_locked_) { task_erase(); task_set_ &= ~T_ERASE; if (target_locked_) { std::cout << " Unit is still locked after erasing" << "\n"; return; } } // Order of checking matters if (!validate_flash_size_options() || !validate_mac_options()) return; if (task_set_ & T_PRESERVE_MAC) { programmer_.unit_mac_address_read(unit_info_.mac_address_count - 1, mac_addr_); std::cout << " MAC address to preserve: " << mac_address_to_string(mac_addr_) << "\n"; task_set_ |= T_WRITE_MAC; } if (task_set_ & T_READ_MAC) task_read_mac_address(); if (task_set_ & T_READ_INFO_PAGE) task_read_info_page(); if (task_set_ & T_RESET) { programmer_.unit_reset(); std::cout << " Target reset" << "\n"; } if (task_set_ & T_READ_FLASH) task_read_flash(); if (task_set_ & T_ERASE) task_erase(); if (task_set_ & T_WRITE_FLASH) { if (task_set_ & T_LOCK) { if (programmer_.flash_image_embed_lock_data(flash_write_data_, lock_data_)) task_set_ &= ~T_LOCK; } if (task_set_ & T_WRITE_MAC) { if (programmer_.flash_image_embed_mac_address(flash_write_data_, mac_addr_)) task_set_ &= ~T_WRITE_MAC; } task_write_flash(); } if (task_set_ & T_VERIFY) task_verify_flash(); if (task_set_ & (T_WRITE_MAC | T_LOCK)) task_write_config(); } //============================================================================== void CC_Flasher::task_test() { std::cout << " Device info: " << "\n"; CC_ProgrammerInfo info; programmer_.programmer_info(info); std::cout << info; if (target_locked_) return; std::cout << "\n"; std::cout << " Target info: " << "\n"; std::cout << unit_info_; std::cout << " Lock data size: " << programmer_.unit_lock_data_size() << " B" << "\n"; } //============================================================================== void CC_Flasher::task_read_mac_address() { ByteVector mac0; programmer_.unit_mac_address_read(0, mac0); if (unit_info_.mac_address_count == 1) std::cout << " MAC address: " << mac_address_to_string(mac0) << "\n"; else { ByteVector mac1; programmer_.unit_mac_address_read(1, mac1); std::cout << " MAC addresses, primary: " << mac_address_to_string(mac0) << ", secondary: " << mac_address_to_string(mac1) << "\n"; } } //============================================================================== void CC_Flasher::task_read_info_page() { if (!(unit_info_.flags & UnitInfo::SUPPORT_INFO_PAGE)) { std::cout << " Target does not reading Info Page" << "\n"; return; } std::cout << " Reading info page..." << "\n"; Timer timer; ByteVector info_page; programmer_.unit_read_info_page(info_page); print_result(true, timer); if (info_page_read_target_.source_type() == ReadTarget::ST_CONSOLE) { std::cout << " Information page (" << info_page.size() << " B):" << "\n"; print_hex_dump(info_page); } else info_page_read_target_.on_read(info_page); } //============================================================================== void CC_Flasher::task_erase() { std::cout << " Erasing flash..." << "\n"; print_result(programmer_.unit_erase()); programmer_.unit_connect(unit_info_); target_locked_ = programmer_.unit_locked(); } //============================================================================== void CC_Flasher::task_verify_flash() { std::cout << " Verifying flash..." << "\n"; Timer timer; bool result = programmer_.unit_flash_verify(flash_write_data_, verify_method_); print_result(result, timer); } //============================================================================== void CC_Flasher::task_read_flash() { size_t size = unit_info_.actual_flash_size() / 1024; std::cout << " Reading flash (" << size << " KB)..." << "\n"; Timer timer; ByteVector flash_data; programmer_.unit_flash_read(flash_data); flash_read_target_.on_read(flash_data); print_result(true, timer); } //============================================================================== void CC_Flasher::task_write_flash() { size_t flash_size = unit_info_.flash_size ? unit_info_.flash_size : unit_info_.max_flash_size; flash_size *= 1024; if (flash_write_data_.upper_address() > flash_size) { std::cout << " Flash image size exceeding flash physical size, writing canceled..." << "\n"; task_set_ &= ~(T_VERIFY | T_LOCK); return; } String size = convinient_storage_size(flash_write_data_.actual_size()); std::cout << " Writing flash (" << size << ")..." << "\n"; Timer timer; programmer_.unit_flash_write(flash_write_data_); print_result(true, timer); } //============================================================================== CC_Flasher::CC_Flasher() : task_set_(0), verify_method_(CC_Programmer::VM_BY_CRC), target_locked_(false) { programmer_.do_on_flash_read_progress(on_progress); programmer_.do_on_flash_write_progress(on_progress); } cc-tool-0.27/src/application/cc_flasher.h000066400000000000000000000024761371037307000203500ustar00rootroot00000000000000/* * cc_tool.cpp * * Created on: Aug 3, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_FLASHER_H_ #define _CC_FLASHER_H_ #include #include "data/binary_file.h" #include "data/hex_file.h" #include "data/read_target.h" #include "data/data_section_store.h" #include "programmer/cc_programmer.h" #include "application/cc_base.h" class CC_Flasher : public CC_Base { public: CC_Flasher(); private: void task_test(); void task_erase(); void task_read_flash(); void task_write_flash(); void task_verify_flash(); void task_read_mac_address(); void task_write_config(); void task_read_info_page(); bool validate_mac_options(); bool validate_lock_options(); bool validate_flash_size_options(); virtual void init_options(po::options_description &); virtual bool read_options(const po::options_description &, const po::variables_map &); virtual void process_tasks(); String option_lock_data_; String option_info_page_; String option_verify_type_; String option_flash_size_; uint_t task_set_; CC_Programmer::VerifyMethod verify_method_; DataSectionStore flash_write_data_; ByteVector mac_addr_; ByteVector lock_data_; ReadTarget flash_read_target_; ReadTarget info_page_read_target_; bool target_locked_; }; #endif // !_CC_FLASHER_H_ cc-tool-0.27/src/common/000077500000000000000000000000001371037307000150625ustar00rootroot00000000000000cc-tool-0.27/src/common/common.cpp000066400000000000000000000046461371037307000170700ustar00rootroot00000000000000/* * common.cpp * * Created on: Nov 11, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "common.h" //============================================================================== uint_t align_up(uint_t value, uint_t aligment) { return ((value + aligment - 1) / aligment) * aligment; } //============================================================================== bool hex_to_binary(const String &hex, ByteVector &out, const char delimiter[]) { const char *str = hex.c_str(); char buffer[3] = { 0, 0, 0 }; while (*str) { while (*str && strchr(delimiter, *str) != NULL) str++; if (!*str) break; buffer[0] = *str++; if (!*str) return false; buffer[1] = *str++; char *error = NULL; out.push_back(std::strtoul(buffer, &error, 16)); if (*error != '\0') return false; } return true; } //============================================================================== String binary_to_hex(const uint8_t data[], size_t size, const char delimiter[]) { std::stringstream ss; ss << std::setfill('0') << std::hex << std::uppercase; while (size--) { ss << std::setw(2) << (int)*data++; if (size) ss << delimiter; } return ss.str(); } //============================================================================== uint_t get_tick_count() { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec * 1000 + tv.tv_usec / 1000); } //============================================================================== String convinient_storage_size(off_t size) { const String measure[] = { " B", " KB", " MB", " GB" }; size_t index = 0; while (size > 1024 && index < (ARRAY_SIZE(measure) - 1)) { size = size / 1024; index++; } return number_to_string(size) + measure[index]; } //============================================================================== String binary_to_hex(const ByteVector &data, const char delimiter[]) { return binary_to_hex(&data[0], data.size(), delimiter); } //============================================================================== void vector_append(ByteVector &vector, const uint8_t data[], size_t size) { vector.insert(vector.end(), data, data + size); } //============================================================================== String &string_append(String &string, const String &item, const char *delimiter) { if (!string.empty()) string.append(delimiter); return string; } cc-tool-0.27/src/common/common.h000066400000000000000000000051131371037307000165230ustar00rootroot00000000000000/* * common.h * * Created on: Aug 3, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _COMMON_H_ #define _COMMON_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define foreach BOOST_FOREACH #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define ALIGN_UP(value, aligment) (((value + (aligment) - 1) / (aligment)) * (aligment)) #define LOBYTE(w) ((uint8_t)(w)) #define HIBYTE(w) ((uint8_t)(((uint16_t)(w) >> 8) & 0xFF)) typedef unsigned int uint_t; typedef std::string String; typedef std::vector StringVector; typedef std::vector ByteVector; typedef std::vector BoolVector; typedef std::vector UintVector; String convinient_storage_size(off_t size); uint_t get_tick_count(); String binary_to_hex(const uint8_t data[], size_t size, const char delimiter[] = ""); String binary_to_hex(const ByteVector &data, const char delimiter[] = ""); void vector_append(ByteVector &vector, const uint8_t data[], size_t size); String& string_append(String &string, const String &item, const char *delimiter); bool hex_to_binary(const String &hex, ByteVector &out, const char delimiter[] = ""); uint_t align_up(uint_t value, uint_t aligment); namespace common_impl { template struct nt { typedef T type; }; template<> struct nt { typedef uint_t type; }; template<> struct nt { typedef int type; }; }; //============================================================================== template inline String number_to_string(T number) { std::stringstream ss; ss << static_cast::type>(number); return ss.str(); } //============================================================================== template inline bool string_to_number(const String &string, T &number) { char *bad_character = NULL; number = strtoul(string.c_str(), &bad_character, 10); return string.empty() || *bad_character == '\0'; } //============================================================================== template inline bool hexstring_to_number(const String &string, T &number) { char *bad_character = NULL; number = strtoul(string.c_str(), &bad_character, 16); return string.empty() || *bad_character == '\0'; } #endif // !_COMMON_H_ cc-tool-0.27/src/common/log.cpp000066400000000000000000000027461371037307000163600ustar00rootroot00000000000000/* * log.cpp * * Created on: Nov 9, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "log.h" #include //============================================================================== Log::Log() : file_(NULL) { } //============================================================================== Log::~Log() { if (file_) fclose(file_); } //============================================================================== void Log::set_log_file(const String &file_name) { if (file_) fclose(file_); file_ = fopen(file_name.c_str(), "w"); } //============================================================================== void Log::add(LogLevel level, const String &message, va_list ap) { time_t sys_time; tm local_time; time(&sys_time); localtime_r(&sys_time, &local_time); char time_stamp[64] = { '\0' }; strftime(time_stamp, 64, "%d.%m %H:%M:%S:", &local_time); sprintf(time_stamp + strlen(time_stamp), "%05d", get_tick_count() % 100000); if (file_) { fprintf(file_, "[%s] ", time_stamp); vfprintf(file_, message.c_str(), ap); fprintf(file_, "\n"); fflush(file_); } } //============================================================================== void log_info(const String &message, ...) { va_list ap; va_start(ap, message); log_get().add(Log::LL_INFO, message, ap); va_end(ap); } //============================================================================== Log &log_get() { static Log log; return log; } cc-tool-0.27/src/common/log.h000066400000000000000000000010071371037307000160120ustar00rootroot00000000000000/* * log.h * * Created on: Nov 9, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _LOG_H_ #define _LOG_H_ #include #include #include #include "common.h" class Log { public: enum LogLevel { LL_INFO }; void add(LogLevel level, const String &message, va_list ap); void set_log_file(const String &file_name); Log(); ~Log(); private: FILE *file_; }; void log_info(const String &message, ...); Log &log_get(); #endif // !_LOG_H_ cc-tool-0.27/src/common/timer.cpp000066400000000000000000000012501371037307000167040ustar00rootroot00000000000000/* * timer.cpp * * Created on: Nov 11, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "timer.h" //============================================================================== Timer::Timer() { start(); } //============================================================================== void Timer::start() { start_time_ = get_tick_count(); } //============================================================================== String Timer::elapsed_time() const { uint_t elapsed_time = get_tick_count() - start_time_; char buf[16]; sprintf(buf, "%.02f s.", (float)elapsed_time / 1000); return buf; } cc-tool-0.27/src/common/timer.h000066400000000000000000000005251371037307000163550ustar00rootroot00000000000000/* * timer.h * * Created on: Nov 5, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _TIMER_H_ #define _TIMER_H_ #include "common.h" class Timer : boost::noncopyable { public: String elapsed_time() const; Timer(); private: void start(); uint_t start_time_; }; #endif // !_TIMER_H_ cc-tool-0.27/src/data/000077500000000000000000000000001371037307000145035ustar00rootroot00000000000000cc-tool-0.27/src/data/binary_file.cpp000066400000000000000000000030361371037307000174740ustar00rootroot00000000000000/* * binary_file.cpp * * Created on: Jul 30, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "binary_file.h" #include "file.h" //============================================================================== void file_io_error(const String &message, const String &file_name) { String error = message + " " + file_name + ": " + strerror(errno); throw FileException(error); } //============================================================================== void binary_file_load(const String &file_name, ByteVector &vector) { FILE *file = fopen(file_name.c_str(), "r"); if (!file) file_io_error("Unable to open file file", file_name); fseek(file, 0, SEEK_END); size_t size = ftell(file); fseek(file, 0, SEEK_SET); vector.resize(size, 0); if (fread(&vector[0], 1, size, file) != size && ferror(file) != 0) { fclose(file); file_io_error("Unable to read file", file_name); } if (fclose(file)) file_io_error("Unable to close file", file_name); //return vector; } //============================================================================== void binary_file_save(const String &file_name, const ByteVector &vector) { FILE *file = fopen(file_name.c_str(), "w"); if (!file) file_io_error("Unable to open file file", file_name); if (fwrite(&vector[0], 1, vector.size(), file) != vector.size() && ferror(file) != 0) { fclose(file); file_io_error("Unable to write file", file_name); } if (fclose(file)) file_io_error("Unable to close file", file_name); } cc-tool-0.27/src/data/binary_file.h000066400000000000000000000005671371037307000171470ustar00rootroot00000000000000/* * binary_file.h * * Created on: Jul 30, 2011 * Author: George Stark * * License: GNU GPL v2 */ #ifndef _BINARY_FILE_H_ #define _BINARY_FILE_H_ #include "common.h" void binary_file_load(const String &file_name, ByteVector &vector); void binary_file_save(const String &file_name, const ByteVector &vector); #endif // !_BINARY_FILE_H_ cc-tool-0.27/src/data/data_section.cpp000066400000000000000000000027751371037307000176570ustar00rootroot00000000000000/* * data_section.cpp * * Created on: Jul 29, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "data_section.h" //============================================================================== std::ostream& operator <<(std::ostream &os, const DataSection &o) { os << std::uppercase << std::hex << std::setfill('0'); os << "start address: " << std::setw(8) << o.address << ", "; os << "end address: " << std::setw(8) << o.next_address() << ", "; os << "size: " << std::setw(8) << o.size(); return os; } //============================================================================== bool DataSection::empty() const { return data.empty(); } //============================================================================== size_t DataSection::size() const { return data.size(); } //============================================================================== uint_t DataSection::next_address() const { return address + data.size(); } //============================================================================== DataSection::DataSection() : address(0) { } //============================================================================== DataSection::DataSection(uint_t address_, const ByteVector &data_) : address(address_), data(data_) { } //============================================================================== DataSection::DataSection(uint_t address_, const uint8_t data_[], size_t size) : address(address_), data(data_, data_ + size) { } cc-tool-0.27/src/data/data_section.h000066400000000000000000000011771371037307000173170ustar00rootroot00000000000000/* * data_section.h * * Created on: Jul 29, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _DATA_SECTION_H_ #define _DATA_SECTION_H_ #include #include "common.h" struct DataSection { bool empty() const; size_t size() const; uint_t next_address() const; DataSection(); DataSection(uint_t address, const ByteVector &data); DataSection(uint_t address, const uint8_t data[], size_t size); uint_t address; ByteVector data; }; typedef std::list DataSectionList; std::ostream& operator <<(std::ostream &os, const DataSection &o); #endif // !_DATA_SECTION_H_ cc-tool-0.27/src/data/data_section_store.cpp000066400000000000000000000126521371037307000210660ustar00rootroot00000000000000/* * data_section_store.cpp * * Created on: Jul 30, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "data_section_store.h" //============================================================================== static bool sections_overlapped( const DataSection §ion1, const DataSection §ion2) { if (section1.address >= section2.address && section1.address < section2.next_address()) return true; if (section2.address >= section1.address && section2.address < section1.next_address()) return true; return false; } //============================================================================== static bool check_section_fit( const DataSectionList §ions, const DataSection §ion) { foreach (const DataSection &item, sections) { if (sections_overlapped(item, section)) return false; } return true; } //============================================================================== static void add_insert_section( DataSectionList §ions, const DataSection §ion) { DataSectionList::iterator it = sections.begin(); for ( ; it != sections.end(); it++) { if (it->address > section.address) { if (it != sections.begin()) --it; break; } } sections.insert(it, section); /// possibly merge } //============================================================================== static void add_replace_section( DataSectionList §ions, const DataSection §ion) { DataSectionList::iterator cur_section = sections.begin(); for (; cur_section != sections.end(); cur_section++) { // new section starts at empty space if (section.address < cur_section->address) { cur_section = sections.insert(cur_section, section); // normalze break; } // new section starts in another section if (cur_section->next_address() > section.address) { uint_t section_offset = section.address - cur_section->address; // simple case: replace a part of existing section, // no size change, no normalize if (cur_section->next_address() >= section.next_address()) { std::copy(section.data.begin(), section.data.end(), cur_section->data.begin() + section_offset); return; } // new section doen't fit current section so resize it and then // normalize cur_section->data.resize(section.next_address() - cur_section->address); std::copy(section.data.begin(), section.data.end(), cur_section->data.begin() + section_offset); break; } } if (cur_section == sections.end()) { sections.push_back(section); /// possibly merge return; } /// normalize sections: DataSectionList::iterator it = cur_section; it++; for (; it != sections.end(); ++it) { if (it->address >= cur_section->next_address()) break; // need merge /// old section completely overlapped by new one, remove it if (it->address >= cur_section->address && it->next_address() <= cur_section->next_address()) { it = sections.erase(it); continue; } /// old section party overlapped by new one, merge them if (it->address >= cur_section->next_address()) { cur_section->data.insert(cur_section->data.end(), it->data.begin() + cur_section->next_address() - it->address, it->data.end()); it = sections.erase(it); } } } //============================================================================== const DataSectionList &DataSectionStore::sections() const { return sections_; } //============================================================================== size_t DataSectionStore::lower_address() const { return sections_.empty() ? 0 : sections_.front().address; } //============================================================================== size_t DataSectionStore::upper_address() const { return sections_.empty() ? 0 : sections_.back().next_address(); } //============================================================================== void DataSectionStore::remove_sections() { sections_.clear(); } //============================================================================== bool DataSectionStore::add_section(const DataSection §ion, bool overwrite) { if (section.empty()) return true; if (!overwrite) { if (!check_section_fit(sections_, section)) return false; add_insert_section(sections_, section); } else add_replace_section(sections_, section); return true; } //============================================================================== bool DataSectionStore::add_sections(const DataSectionStore &store, bool overwrite) { if (!overwrite) { foreach (const DataSection &item, store.sections()) { if (check_section_fit(sections_, item)) return false; } foreach (const DataSection &item, store.sections()) add_insert_section(sections_, item); } else foreach (const DataSection &item, store.sections()) add_replace_section(sections_, item); return true; } //============================================================================== void DataSectionStore::create_image(uint8_t filler, ByteVector &image) const { image.resize(upper_address(), 0); std::fill(image.begin(), image.end(), filler); foreach (const DataSection §ion, sections_) std::copy(section.data.begin(), section.data.end(), &image[section.address]); } //============================================================================== size_t DataSectionStore::actual_size() const { size_t size = 0; foreach (const DataSection §ion, sections_) size += section.data.size(); return size; } cc-tool-0.27/src/data/data_section_store.h000066400000000000000000000023241371037307000205260ustar00rootroot00000000000000/* * data_section_store.h * * Created on: Jul 29, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _DATA_SECTION_STORE_H_ #define _DATA_SECTION_STORE_H_ #include "common.h" #include "data_section.h" /// Class store and manage a list of DataSections object in (accednig not-overlapped order) class DataSectionStore { public: /// Return sum of all sections' sizes size_t actual_size() const; /// Return the minor valid address size_t lower_address() const; /// Return the address next to the most one size_t upper_address() const; /// Add section to the store /// @return false if section overlapped and overwrite is false bool add_section(const DataSection &data, bool overwrite); /// Add all of DataSectionStore object's sections to the store /// @return false if section overlapped and overwrite is false bool add_sections(const DataSectionStore §ion_store, bool overwrite); /// Remove all sections void remove_sections(); /// Unite all sections to one continuoys memory block void create_image(uint8_t filler, ByteVector &image) const; const DataSectionList §ions() const; private: DataSectionList sections_; }; #endif // !_DATA_SECTION_STORE_H_ cc-tool-0.27/src/data/file.cpp000066400000000000000000000070561371037307000161360ustar00rootroot00000000000000/* * file.cpp * * Created on: Aug 4, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include #include #include "file.h" //============================================================================== inline void check_open(const String &context, FILE *file) { if (!file) throw FileException(context + " on not opened file"); } //============================================================================== inline void file_io_error(const String &context, const String &file_name) { String error = context + " failed, file name: " + file_name + ": " + strerror(errno); throw FileException(error); } //============================================================================== File::File() : file_(NULL) { } //============================================================================== File::~File() { if (file_ != NULL) fclose(file_); } //============================================================================== void File::open(const String &file_name, const char mode[], off_t max_size) { close(); file_name_ = file_name; file_ = fopen(file_name.c_str(), mode); if (file_ == NULL) file_io_error("File::open", file_name_); if (max_size && max_size < size()) { close(); throw FileException("File " + file_name + " is too long"); } } //============================================================================== void File::close() { if (file_ != NULL) if (fclose(file_) < 0) file_io_error("File::close", file_name_); file_ = NULL; } //============================================================================== off_t File::size() { check_open("File::size", file_); struct stat file_stat; if (fstat(fileno(file_), &file_stat) != 0) file_io_error("File::size", file_name_); return file_stat.st_size; } //============================================================================== off_t File::seek(off_t offset, uint_t position) { check_open("File::seek", file_); off_t result = fseeko(file_, offset, position); if (result == (off_t) -1) file_io_error("File::seek", file_name_); return result; } //============================================================================== void File::write(const uint8_t data[], size_t size) { check_open("File::write", file_); if (fwrite(data, size, 1, file_) != 1 || ferror(file_)) file_io_error("File::write", file_name_); } //============================================================================== void File::write(const ByteVector &data) { check_open("File::write", file_); if (fwrite(&data[0], data.size(), 1, file_) != 1 || ferror(file_)) file_io_error("File::write", file_name_); } //============================================================================== void File::read(uint8_t data[], size_t size) { check_open("File::read", file_); if (fread(data, size, 1, file_) != 1 || ferror(file_)) file_io_error("File::read", file_name_); } //============================================================================== void File::read(ByteVector &data, size_t size) { check_open("File::read", file_); data.resize(size); if (fread(&data[0], data.size(), 1, file_) != 1 || ferror(file_)) file_io_error("File::read", file_name_); } //============================================================================== bool File::read_n(uint8_t data[], size_t max_size, size_t &read_size) { check_open("File::read_max", file_); ssize_t result = fread(data, 1, max_size, file_); if (ferror(file_)) file_io_error("File::read_max", file_name_); read_size = result; return feof(file_); } cc-tool-0.27/src/data/file.h000066400000000000000000000016461371037307000156020ustar00rootroot00000000000000/* * file.h * * Created on: Aug 1, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _FILE_H_ #define _FILE_H_ #include "common.h" class File //: boost::noncopyable { public: void open(const String &file_name, const char mode[], off_t max_size = 0); // throw void close(); // throw off_t size(); // throw off_t seek(off_t offset, uint_t position); // throw void write(const uint8_t data[], size_t size); // throw void write(const ByteVector &data); // throw void read(uint8_t data[], size_t size); // throw void read(ByteVector &data, size_t size); // throw // return false if eof bool read_n(uint8_t data[], size_t max_size, size_t &read_size); // throw File(); ~File(); private: FILE *file_; String file_name_; }; class FileException : public std::runtime_error { public: FileException(const String& arg) : std::runtime_error(arg) { } }; #endif // !_FILE_H_ cc-tool-0.27/src/data/hex_file.cpp000066400000000000000000000244061371037307000170000ustar00rootroot00000000000000/* * hex_file.cpp * * Created on: Jul 22, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include #include "file.h" #include "hex_file.h" void file_io_error(const String &message, const String &file_name); // throw class HexDataReader { public: enum Error { ERROR_OK, ERROR_RECORD_CRC_MISMATCH, ERROR_RECORD_NO_HEADER, ERROR_RECORD_BAD_FORMAT, ERROR_RECORD_UNKNOWN_TYPE, ERROR_RECORD_SIZE_MISMATCH, ERROR_RECORD_BAD_CHARACTER, ERROR_SECTION_OVERLAPPING, }; Error read_next_record(const String &record_line); Error read_complete(); HexDataReader(DataSectionStore §ions, bool ignore_crc, bool allow_overlapping_records); private: DataSectionStore &store_; uint_t address_prefix_; bool section_started_; //Error error_; DataSection section_; bool ignore_crc_; bool allow_overlapping_records_; }; struct Record { enum Type { RT_DATA = 0, RT_EOF = 1, RT_EX_SEGMENT_ADDRESS = 2, RT_START_SEGMENT_ADDRESS = 3, RT_EX_LINEAR_ADDRESS = 4, RT_START_LINEAR_ADDRESS = 5, MAX_TYPE_NUMBER = RT_START_LINEAR_ADDRESS, }; Type type; uint_t address; ByteVector data; }; static void hex_file_error( const String &file_name, HexDataReader::Error error, uint_t line_number); // throw //============================================================================== std::ostream& operator <<(std::ostream &os, const Record &o) { os << "Type: "; if (o.type == Record::RT_DATA) os << "Data"; if (o.type == Record::RT_EOF) os << "End Of File"; if (o.type == Record::RT_EX_SEGMENT_ADDRESS) os << "Extended Segment Address"; if (o.type == Record::RT_START_SEGMENT_ADDRESS) os << "Start Segment Address"; if (o.type == Record::RT_EX_LINEAR_ADDRESS) os << "Extended Linear Address"; if (o.type == Record::RT_START_LINEAR_ADDRESS) os << "Start Linear Address "; os << ", "; os << std::uppercase << std::hex << std::setfill('0'); os << "address: " << std::setw(8) << o.address << ", "; os << "size: " << std::dec << o.data.size(); return os; } //============================================================================== static bool hex_to_byte(char low_part, char high_part, uint8_t &out_byte) { if (!isxdigit(low_part) || !isxdigit(high_part)) return false; char buffer[3] = { low_part, high_part, 0 }; out_byte = strtoul(buffer, NULL, 16); return true; } //============================================================================== static bool hex_to_binary(const char data[], size_t size, uint8_t out[]) { for (size_t i = 0; i < size; i += 2) { if (!hex_to_byte(data[i], data[i + 1], out[i / 2])) return false; } return true; } //============================================================================== static uint_t make_word(uint8_t low_byte, uint8_t high_byte, bool big_endian = true) { return big_endian ? (low_byte << 8) | high_byte : (high_byte << 8) | low_byte; } //============================================================================== static HexDataReader::Error parse_record(const String &line, Record &record, bool ignore_crc) { if (line[0] != ':') return HexDataReader::ERROR_RECORD_NO_HEADER; if (!(line.size() % 2) || line.size() > 1024) return HexDataReader::ERROR_RECORD_SIZE_MISMATCH; size_t record_size = line.size() / 2; uint8_t data[record_size]; if (!hex_to_binary(line.c_str() + 1, line.size() - 1, data)) return HexDataReader::ERROR_RECORD_BAD_CHARACTER; uint8_t crc = 0; if (!ignore_crc && std::accumulate(data, data + record_size, crc) != 0) return HexDataReader::ERROR_RECORD_CRC_MISMATCH; uint8_t data_size = data[0]; if (data_size != (record_size - 5)) // 5 - header size return HexDataReader::ERROR_RECORD_SIZE_MISMATCH; uint8_t record_type = data[3]; if (record_type > Record::MAX_TYPE_NUMBER) return HexDataReader::ERROR_RECORD_UNKNOWN_TYPE; if (record_type == Record::RT_DATA) record.data.assign(data + 4, data + 4 + data_size); else record.data.clear(); uint_t address = make_word(data[1], data[2]); if (record_type == Record::RT_EX_SEGMENT_ADDRESS) { if (data_size != 2 || address) return HexDataReader::ERROR_RECORD_BAD_FORMAT; address = make_word(data[4], data[5]) << 4; } if (record_type == Record::RT_EX_LINEAR_ADDRESS) { if (data_size != 2 || address) return HexDataReader::ERROR_RECORD_BAD_FORMAT; address = make_word(data[4], data[5]) << 16; } record.type = (Record::Type)record_type; record.address = address; return HexDataReader::ERROR_OK; } //============================================================================== HexDataReader::HexDataReader(DataSectionStore &store, bool ignore_crc, bool allow_overlapping_records) : store_(store), address_prefix_(0), section_started_(false), ignore_crc_(ignore_crc), allow_overlapping_records_(allow_overlapping_records) { } // Do not pass empty lines here! //============================================================================== HexDataReader::Error HexDataReader::read_next_record(const String &record_line) { Record record; HexDataReader::Error error = parse_record(record_line, record, ignore_crc_); if (error != ERROR_OK) return error; if (record.type == Record::RT_EOF) return ERROR_OK; if (record.type == Record::RT_DATA) { record.address |= address_prefix_; if (section_started_ && section_.next_address() != record.address) { if (!store_.add_section(section_, allow_overlapping_records_)) return ERROR_SECTION_OVERLAPPING; section_.data.clear(); section_started_ = false; } if (!section_started_) { section_started_ = true; section_.address = record.address; } section_.data.insert(section_.data.end(), record.data.begin(), record.data.end()); } if (record.type == Record::RT_EX_SEGMENT_ADDRESS) address_prefix_ = record.address; if (record.type == Record::RT_EX_LINEAR_ADDRESS) address_prefix_ = record.address; return ERROR_OK; } //============================================================================== HexDataReader::Error HexDataReader::read_complete() { if (section_started_ && !store_.add_section(section_, allow_overlapping_records_)) return ERROR_SECTION_OVERLAPPING; return ERROR_OK; } //============================================================================== void hex_file_load(const String &file_name, DataSectionStore §ion_store, bool ignore_crc_mismatch, bool allow_overlapping_records) { std::ifstream in(file_name.c_str()); if (!in) throw std::runtime_error("Unable to open file " + file_name); HexDataReader::Error error = HexDataReader::ERROR_OK; uint_t line_number = 0; HexDataReader reader(section_store, ignore_crc_mismatch, allow_overlapping_records); String record_line; while (in) { line_number++; std::getline(in, record_line); if (!record_line.empty() && *record_line.rbegin() == '\r') record_line.erase(record_line.end() - 1); if (record_line.empty()) continue; error = reader.read_next_record(record_line); if (error != HexDataReader::ERROR_OK) hex_file_error(file_name, error, line_number); } error = reader.read_complete(); if (error != HexDataReader::ERROR_OK) hex_file_error(file_name, error, line_number); //return section_store; } //============================================================================== static void write_eof_record(std::ostream &out) { out << ":00000001FF"; out << "\r\n"; } //============================================================================== static void write_data_record(std::ostream &out, uint_t address, const uint8_t data[], size_t size) { const uint8_t buffer[] = { LOBYTE(size), HIBYTE(address), LOBYTE(address), 0x00 }; uint8_t crc = 0; crc = std::accumulate(buffer, buffer + ARRAY_SIZE(buffer), crc); crc = std::accumulate(data, data + size, crc); crc = 0x100 - crc; out << ":"; out << binary_to_hex(buffer, ARRAY_SIZE(buffer)); out << binary_to_hex(data, size); out << binary_to_hex(&crc, 1); out << "\r\n"; } //============================================================================== static void write_segment_record(std::ostream &out, uint16_t address) { const uint8_t buffer[] = { 0x02, 0x00, 0x00, 0x02, HIBYTE(address), LOBYTE(address) }; uint8_t crc = 0; crc = 0x100 - std::accumulate(buffer, buffer + ARRAY_SIZE(buffer), crc); out << ":"; out << binary_to_hex(buffer, ARRAY_SIZE(buffer)); out << binary_to_hex(&crc, 1); out << "\r\n"; } //============================================================================== void hex_file_save(const String &file_name, const DataSectionStore §ion_store) { std::ofstream out(file_name.c_str()); if (!out) throw FileException("Unable to open file" + file_name); uint_t offset = 0; foreach (const DataSection §ion, section_store.sections()) { uint_t address = section.address; uint_t size = section.size(); while (size) { if ((address - offset) > 0xFFFF) { offset = address & ~0x0F; write_segment_record(out, offset >> 4); } const uint_t RECORD_MAX_DATA_SIZE = 16; const uint_t record_size = std::min(RECORD_MAX_DATA_SIZE, size); write_data_record(out, address - offset, §ion.data[address - section.address], record_size); address += record_size; size -= record_size; } } write_eof_record(out); } //============================================================================== static void hex_file_error( const String &file_name, HexDataReader::Error error, uint_t line_number) { std::stringstream ss; ss << "File '" << file_name << "' load error: "; switch (error) { case HexDataReader::ERROR_RECORD_CRC_MISMATCH: ss << "CRC mismatch, line: " << line_number; break; case HexDataReader::ERROR_RECORD_NO_HEADER: ss << "Record header not found, line: " << line_number; break; case HexDataReader::ERROR_RECORD_BAD_FORMAT: ss << "Record format error, line: " << line_number; break; case HexDataReader::ERROR_RECORD_UNKNOWN_TYPE: ss << "Unknown record type, line: " << line_number; break; case HexDataReader::ERROR_RECORD_SIZE_MISMATCH: ss << "Record size mismatch, line: " << line_number; break; case HexDataReader::ERROR_RECORD_BAD_CHARACTER: ss << "Unexpected character, line: " << line_number; break; case HexDataReader::ERROR_SECTION_OVERLAPPING: ss << "Sections overlapped"; break; case HexDataReader::ERROR_OK: default: ss << "ok"; } throw FileException(ss.str()); } cc-tool-0.27/src/data/hex_file.h000066400000000000000000000007531371037307000164440ustar00rootroot00000000000000/* * hex_file.h * * Created on: Jul 15, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _HEX_FILE_H_ #define _HEX_FILE_H_ #include "common.h" #include "data_section_store.h" void hex_file_load(const String &file_name, DataSectionStore §ion_store, bool ignore_crc_mismatch = false, bool allow_overlapping_records = false); void hex_file_save(const String &file_name, const DataSectionStore §ion_store); #endif // !_HEX_FILE_H_ cc-tool-0.27/src/data/progress_watcher.cpp000066400000000000000000000046741371037307000206030ustar00rootroot00000000000000/* * progress_watcher.cpp * * Created on: Nov 12, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "progress_watcher.h" //============================================================================== void ProgressWatcher::do_on_read_progress(const OnProgress::slot_type &slot) { on_read_progress_.connect(slot); } //============================================================================== void ProgressWatcher::do_on_write_progress(const OnProgress::slot_type &slot) { on_write_progress_.connect(slot); } //============================================================================== void ProgressWatcher::read_progress(uint_t done_chunk) { if (enabled_ && read_started_ && done_chunk) { done_read_ += done_chunk; on_read_progress_(done_read_, total_read_); } } //============================================================================== void ProgressWatcher::write_progress(uint_t done_chunk) { if (enabled_ && write_started_ && done_chunk) { done_write_ += done_chunk; on_write_progress_(done_write_, total_write_); } } //============================================================================== void ProgressWatcher::read_start(size_t total_size) { if (!enabled_) return; read_started_ = true; total_read_ = total_size; done_read_ = 0; } //============================================================================== void ProgressWatcher::read_finish() { if (!enabled_) return; read_started_ = false; if (done_read_ != total_read_) on_read_progress_(total_read_, total_read_); } //============================================================================== void ProgressWatcher::write_start(size_t total_size) { if (!enabled_) return; write_started_ = true; total_write_ = total_size; done_write_ = 0; } //============================================================================== void ProgressWatcher::write_finish() { if (!enabled_) return; write_started_ = false; if (done_write_ != total_write_) on_write_progress_(done_write_, total_write_); } //============================================================================== void ProgressWatcher::enable(bool enable) { enabled_ = enable; } //============================================================================== ProgressWatcher::ProgressWatcher() : total_read_(0), total_write_(0), read_started_(false), write_started_(false), done_read_(0), done_write_(0), enabled_(true) { } cc-tool-0.27/src/data/progress_watcher.h000066400000000000000000000020061371037307000202330ustar00rootroot00000000000000/* * progress_watcher.h * * Created on: Nov 12, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _PROGRESS_WATCHER_H_ #define _PROGRESS_WATCHER_H_ #include "common.h" #include class ProgressWatcher : boost::noncopyable { public: typedef boost::signals2::signal OnProgress; void do_on_read_progress(const OnProgress::slot_type &slot); void do_on_write_progress(const OnProgress::slot_type &slot); void read_progress(uint_t done_chunk_size); void write_progress(uint_t done_chunk_size); void read_start(size_t total_size); void read_finish(); void write_start(size_t total_size); void write_finish(); void enable(bool enable); ProgressWatcher(); private: uint_t total_read_; uint_t total_write_; bool read_started_; bool write_started_; uint_t done_read_; uint_t done_write_; bool enabled_; OnProgress on_read_progress_; OnProgress on_write_progress_; }; #endif // !_PROGRESS_WATCHER_H_ cc-tool-0.27/src/data/read_target.cpp000066400000000000000000000053661371037307000175020ustar00rootroot00000000000000/* * read_traget.cpp * * Created on: Oct 31, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include #include "data/data_section_store.h" #include "data/hex_file.h" #include "data/binary_file.h" #include "read_target.h" #include "common/common.h" //============================================================================== static String file_extension(const String path) { #if BOOST_FILESYSTEM_VERSION >= 3 return boost::filesystem::path(path).extension().string(); #else return boost::filesystem::extension(path); #endif } //============================================================================== ReadTarget::ReadTarget() : source_type_(ST_CONSOLE) { } //============================================================================== ReadTarget::SourceType ReadTarget::source_type() const { return source_type_; } //============================================================================== void ReadTarget::on_read(const ByteVector &data) const { if (file_format_ == "hex") { DataSectionStore store; store.add_section(DataSection(0, data), true); hex_file_save(file_name_, store); } if (file_format_ == "bin") binary_file_save(file_name_, data); } //============================================================================== void ReadTarget::set_source(const String &input) { if (input.empty()) source_type_ = ST_CONSOLE; else { OptionFileInfo file_info; option_extract_file_info(input, file_info, false); source_type_ = ST_FILE; file_format_ = file_info.type; file_name_ = file_info.name; } } //============================================================================== void option_extract_file_info(const String &input, OptionFileInfo &file_info, bool support_offset) { StringVector strs; boost::split(strs, input, boost::is_any_of(":")); if (strs.size() > 3) throw std::runtime_error("bad file name format (" + input + ")"); file_info.offset = 0; file_info.name = strs[0]; if (strs.size() > 1) file_info.type = strs[1]; if (file_info.type.empty()) { file_info.type = file_extension(file_info.name); if (file_info.type[0] == '.') file_info.type.erase(0, 1); } if (strs.size() > 2) { if (!string_to_number(strs[2], file_info.offset)) throw std::runtime_error("bad offset value (" + input + ")"); if (!support_offset) throw std::runtime_error("offset is not allowed here (" + input + ")"); } String type; if (file_info.type.empty() || file_info.type == "bin" || file_info.type == "binary") type = "bin"; if (file_info.type == "hex" || file_info.type == "ihex") type = "hex"; if (type.empty()) throw std::runtime_error("unknown file type (" + input + ")"); file_info.type = type; } cc-tool-0.27/src/data/read_target.h000066400000000000000000000012641371037307000171400ustar00rootroot00000000000000/* * read_traget.h * * Created on: Oct 31, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _READ_TARGET_H_ #define _READ_TARGET_H_ #include "common.h" struct OptionFileInfo { String type; String name; size_t offset; }; void option_extract_file_info(const String &input, OptionFileInfo &file_info, bool support_offset); class ReadTarget { public: enum SourceType { ST_CONSOLE, ST_FILE }; SourceType source_type() const; void set_source(const String &input); void on_read(const ByteVector &data) const; ReadTarget(); private: String file_format_; String file_name_; SourceType source_type_; }; #endif // !_READ_TARGET_H_ cc-tool-0.27/src/main.cpp000066400000000000000000000005731371037307000152270ustar00rootroot00000000000000/* * main.cpp * * Created on: Jul 28, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "application/cc_flasher.h" //============================================================================== int main(int argc, char **argv) { CC_Flasher cc_flasher; return cc_flasher.execute(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE; } cc-tool-0.27/src/programmer/000077500000000000000000000000001371037307000157455ustar00rootroot00000000000000cc-tool-0.27/src/programmer/cc_243x.cpp000066400000000000000000000121411371037307000176150ustar00rootroot00000000000000/* * cc_243x.cpp * * Created on: Nov 9, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "log.h" #include "cc_debug_interface.h" #include "cc_243x.h" const uint16_t XREG_FMAP = 0xDF9F; //============================================================================== CC_243x::CC_243x(USB_Device &programmer, ProgressWatcher &pw) : CC_UnitDriver(programmer, pw) { UnitCoreInfo reg_info; reg_info.lock_size = 1; reg_info.flash_word_size = 4; reg_info.write_block_size = 1024; reg_info.verify_block_size = 1024; reg_info.xbank_offset = 0x8000; reg_info.dma0_cfg_offset = 0x0800; reg_info.dma_data_offset = 0x0000; reg_info.memctr = 0xDFC7; reg_info.fmap = XREG_FMAP; reg_info.faddrh = 0xDFAD; reg_info.faddrl = 0xDFAC; reg_info.fctl = 0xDFAE; reg_info.fwdata = 0xDFAF;// reg_info.rndh = 0xDFBD; reg_info.rndl = 0xDFBC; reg_info.dma0_cfgh = 0xDFD5; reg_info.dma0_cfgl = 0xDFD4; reg_info.dma_arm = 0xDFD6; reg_info.dma_req = 0xDFD7; reg_info.dma_irq = 0xDFD1; reg_info.fctl_write = 0x02; set_reg_info(reg_info); } //============================================================================== void CC_243x::supported_units(Unit_ID_List &units) { units.push_back(Unit_ID(0x2430, "CC2430")); units.push_back(Unit_ID(0x2431, "CC2431")); } //============================================================================== void CC_243x::find_unit_info(UnitInfo &unit_info) { unit_info.flags = UnitInfo::SUPPORT_MAC_ADDRESS; unit_info.max_flash_size = 128; unit_info.flash_page_size = 2; unit_info.mac_address_count = 1; unit_info.mac_address_size = 8; unit_info.flash_sizes.push_back(32); unit_info.flash_sizes.push_back(64); unit_info.flash_sizes.push_back(128); ByteVector sfr; read_xdata_memory(0xDF60, 2, sfr); unit_info.revision = sfr[0]; unit_info.internal_ID = sfr[1]; // Possible flash sizes: 32, 64, 128 /* log_info("! getting flash size begin");/// unit_info.flash_size = 32; for (uint8_t i = 1; i < 3; i++) { write_xdata_memory(XREG_FMAP, i); uint8_t result = read_xdata_memory(XREG_FMAP); if (result != i) { log_info("%02Xh, n: %02Xh", i, result); break; } unit_info.flash_size = 32 << i; } log_info("! getting flash size end, result: %u", unit_info.flash_size);/// */ unit_info_ = unit_info; } //============================================================================== bool CC_243x::erase_check_comleted() { uint8_t status = 0; read_debug_status(status); return (status & DEBUG_STATUS_CHIP_ERASE_BUSY); } //============================================================================== void CC_243x::mac_address_read(size_t index, ByteVector &mac_address) { read_xdata_memory(0xDF43, unit_info_.mac_address_size, mac_address); } //============================================================================== void CC_243x::flash_write(const DataSectionStore §ions) { write_flash_slow(sections); } //============================================================================== void CC_243x::flash_read_block(size_t offset, size_t size, ByteVector &data) { flash_read(offset, size, data); } //============================================================================== bool CC_243x::flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address) { if (!unit_info_.flash_size) return false; const uint_t mac_offset = unit_info_.flash_size * 1024 - unit_info_.mac_address_size; DataSection section(mac_offset, mac_address); sections.add_section(section, true); return true; } //============================================================================== void CC_243x::convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data) { uint8_t lock_size[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; convert_lock_data_std_set( qualifiers, ByteVector(lock_size, lock_size + ARRAY_SIZE(lock_size)), lock_data); } //============================================================================== bool CC_243x::config_write(const ByteVector &mac_address, const ByteVector &lock_data) { if (!lock_data.empty()) write_lock_to_info_page(lock_data[0]); if (!mac_address.empty()) { if (!unit_info_.flash_size) { std::cout << " unable to determine flash size. Writing mac is unsupported" << "\n"; return true; } CHECK_PARAM(mac_address.size() == unit_info_.mac_address_size); const uint_t page_size = unit_info_.flash_page_size * 1024; const uint_t page_offset = unit_info_.flash_size * 1024 - page_size; ByteVector block; flash_read_start(); flash_read(page_offset, page_size, block); flash_read_end(); if (!empty_block(&block[0], block.size())) erase_page(page_offset / page_size); const uint_t mac_offset = unit_info_.flash_size * 1024 - mac_address.size(); memcpy(&block[mac_offset - page_offset], &mac_address[0], mac_address.size()); DataSectionStore store; store.add_section(DataSection(page_offset, block), true); write_flash_slow(store); ByteVector check_block; flash_read_start(); flash_read(page_offset, page_size, check_block); flash_read_end(); return memcmp(&check_block[0], &block[0], block.size()) == 0; } return true; } cc-tool-0.27/src/programmer/cc_243x.h000066400000000000000000000017101371037307000172620ustar00rootroot00000000000000/* * cc_243x.h * * Created on: Nov 9, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_243X_H_ #define _CC_243X_H_ #include "cc_unit_driver.h" class CC_243x : public CC_UnitDriver { public: virtual void supported_units(Unit_ID_List &units); virtual void find_unit_info(UnitInfo &info); virtual bool erase_check_comleted(); virtual void mac_address_read(size_t index, ByteVector &mac_address); virtual void flash_write(const DataSectionStore §ions); virtual void flash_read_block(size_t offset, size_t size, ByteVector &data); virtual bool flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address); virtual void convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data); virtual bool config_write(const ByteVector &mac_address, const ByteVector &lock_data); CC_243x(USB_Device &programmer, ProgressWatcher &pw); }; #endif // !_CC_243X_H_ cc-tool-0.27/src/programmer/cc_251x_111x.cpp000066400000000000000000000061641371037307000203760ustar00rootroot00000000000000/* * cc_251x_111x.cpp * * Created on: Nov 10, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "cc_251x_111x.h" #include "cc_debug_interface.h" const uint16_t XDATA_RAM_OFFSET = 0xF000; const uint16_t XDATA_SFR_OFFSET = 0xDF00; //============================================================================== CC_251x_111x::CC_251x_111x(USB_Device &programmer, ProgressWatcher &pw) : CC_UnitDriver(programmer, pw) { UnitCoreInfo reg_info; reg_info.lock_size = 1; reg_info.flash_word_size = 2; reg_info.verify_block_size = 512; reg_info.write_block_size = 512; reg_info.xbank_offset = 0; reg_info.dma0_cfg_offset = XDATA_RAM_OFFSET + 0x0F00; reg_info.dma_data_offset = XDATA_RAM_OFFSET + 0x0000; reg_info.rndh = 0xDFBD; reg_info.rndl = 0xDFBC; reg_info.dma0_cfgh = 0xDFD5; reg_info.dma0_cfgl = 0xDFD4; reg_info.dma_arm = 0xDFD6; reg_info.dma_req = 0xDFD7; reg_info.dma_irq = 0xDFD1; reg_info.fctl = 0xDFAE; reg_info.fwdata = 0xDFAF; reg_info.faddrl = 0xDFAC; reg_info.faddrh = 0xDFAD; reg_info.fctl_write = 0x02; set_reg_info(reg_info); } //============================================================================== void CC_251x_111x::supported_units(Unit_ID_List &units) { units.push_back(Unit_ID(0x2510, "CC2510")); units.push_back(Unit_ID(0x2511, "CC2511")); units.push_back(Unit_ID(0x1111, "CC1111")); units.push_back(Unit_ID(0x1110, "CC1110")); } //============================================================================== void CC_251x_111x::find_unit_info(UnitInfo &unit_info) { unit_info.max_flash_size = 32; unit_info.flash_page_size = 1; unit_info.flags = UnitInfo::SUPPORT_INFO_PAGE; ByteVector sfr; read_xdata_memory(0xDF36, 2, sfr); unit_info.revision = sfr[0]; unit_info.internal_ID = sfr[1]; unit_info.flash_sizes.push_back(8); unit_info.flash_sizes.push_back(16); unit_info.flash_sizes.push_back(32); unit_info_ = unit_info; } //============================================================================== bool CC_251x_111x::erase_check_comleted() { uint8_t status = 0; read_debug_status(status); return (status & DEBUG_STATUS_CHIP_ERASE_BUSY); } //============================================================================== void CC_251x_111x::flash_read_block(size_t offset, size_t size, ByteVector &data) { flash_read_near(offset, size, data); } //============================================================================== void CC_251x_111x::flash_write(const DataSectionStore §ions) { write_flash_slow(sections); } //============================================================================== bool CC_251x_111x::config_write(const ByteVector &mac_address, const ByteVector &lock_data) { if (!lock_data.empty()) write_lock_to_info_page(lock_data[0]); return true; } //============================================================================== void CC_251x_111x::convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data) { uint8_t lock_size[] = { 0, 1, 2, 4, 8, 16, 24, 32 }; convert_lock_data_std_set( qualifiers, ByteVector(lock_size, lock_size + ARRAY_SIZE(lock_size)), lock_data); } cc-tool-0.27/src/programmer/cc_251x_111x.h000066400000000000000000000014621371037307000200370ustar00rootroot00000000000000/* * cc_251x_111x.h * * Created on: Nov 9, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_251X_111X_H_ #define _CC_251X_111X_H_ #include "cc_unit_driver.h" class CC_251x_111x : public CC_UnitDriver { public: virtual void supported_units(Unit_ID_List &units); virtual void find_unit_info(UnitInfo &info); virtual bool erase_check_comleted(); virtual void flash_write(const DataSectionStore §ions); virtual void flash_read_block(size_t offset, size_t size, ByteVector &data); virtual bool config_write(const ByteVector &mac_address, const ByteVector &lock_data); virtual void convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data); CC_251x_111x(USB_Device &programmer, ProgressWatcher &pw); }; #endif // !_CC_251X_111X_H_ cc-tool-0.27/src/programmer/cc_253x_254x.cpp000066400000000000000000000327031371037307000204060ustar00rootroot00000000000000/* * cc_253x_254x.cpp * * Created on: Aug 4, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "log.h" #include "cc_253x_254x.h" #include "data/hex_file.h" #include "data/binary_file.h" const size_t LOCK_DATA_SIZE = 16; const size_t MAX_PAGE_COUNT = LOCK_DATA_SIZE * 8; const size_t INFO_PAGE_OFFSET = 0x7800; const size_t INFO_PAGE_SIZE = 0x800; const uint16_t XREG_DBGDATA = 0x6260; const uint16_t XREG_FWDATA = 0x6273; const uint16_t XREG_FCTL = 0x6270; const uint16_t XREG_FADDRL = 0x6271; const uint16_t XREG_FADDRH = 0x6272; const uint16_t XREG_DMA1CFGL = 0x70D2; const uint16_t XREG_DMA1CFGH = 0x70D3; const uint16_t XREG_DMAARM = 0x70D6; const uint16_t XREG_DMAREQ = 0x70D7; const uint16_t XREG_DMAIRQ = 0x70D1; const uint16_t XREG_MEMCTR = 0x70C7; const uint16_t XREG_FMAP = 0x709F; //============================================================================== static void read_range(const String& input, BoolVector& range, uint_t min_value, uint_t max_value) { boost::cmatch what; boost::regex exp("(\\d{1,})-(\\d{1,})"); StringVector list; boost::split(list, input, boost::is_any_of(",")); foreach(const String& item, list) { uint_t n = 0; uint_t r1, r2; if (string_to_number(item, n)) r1 = r2 = n; else { if (!boost::regex_match(item.c_str(), what, exp)) throw std::runtime_error("read_range: incorrect input"); string_to_number(what[1].str(), r1); string_to_number(what[2].str(), r2); if (r1 > r2) std::swap(r1, r2); } if (r2 > max_value || r1 < min_value) throw std::runtime_error("read_range: value is out of range"); if (range.size() <= r2) range.resize(r2 + 1, false); for (; r1 <= r2; r1++) range[r1] = true; } } //============================================================================== CC_253x_254x::CC_253x_254x(USB_Device &usb_device, ProgressWatcher &pw) : CC_UnitDriver(usb_device, pw) { UnitCoreInfo reg_info; reg_info.lock_size = 16; reg_info.flash_word_size = 4; reg_info.write_block_size = 1024; reg_info.verify_block_size = 1024; reg_info.xbank_offset = 0x8000; reg_info.dma0_cfg_offset = 0x0800; reg_info.dma_data_offset = 0x0000; reg_info.memctr = XREG_MEMCTR; reg_info.fmap = XREG_FMAP; reg_info.faddrh = XREG_FADDRH; reg_info.faddrl = XREG_FADDRL; reg_info.fctl = XREG_FCTL; reg_info.fwdata = XREG_FWDATA; reg_info.rndh = 0x70BD; reg_info.rndl = 0x70BC; reg_info.dma0_cfgh = 0x70D5; reg_info.dma0_cfgl = 0x70D4; reg_info.dma_arm = XREG_DMAARM; reg_info.dma_req = XREG_DMAREQ; reg_info.dma_irq = XREG_DMAIRQ; reg_info.fctl_write = 0x06; set_reg_info(reg_info); } //============================================================================== void CC_253x_254x::supported_units(Unit_ID_List &units) { units.push_back(Unit_ID(0x2530, "CC2530")); units.push_back(Unit_ID(0x2531, "CC2531")); units.push_back(Unit_ID(0x2533, "CC2533")); units.push_back(Unit_ID(0x2540, "CC2540")); units.push_back(Unit_ID(0x2541, "CC2541")); units.push_back(Unit_ID(0x2543, "CC2543")); units.push_back(Unit_ID(0x2544, "CC2544")); units.push_back(Unit_ID(0x2545, "CC2545")); } //============================================================================== void CC_253x_254x::find_unit_info(UnitInfo &unit_info) { bool small_unit = unit_info.ID == 0x2543 || unit_info.ID == 0x2544 || unit_info.ID == 0x2545; unit_info.flags = UnitInfo::SUPPORT_INFO_PAGE; ByteVector sfr; read_xdata_memory(0x6276, 2, sfr); if (sfr[0] & 0x08) unit_info.flags |= UnitInfo::SUPPORT_USB; unit_info.ram_size = (sfr[1] & 0x07) + 1; uint8_t flash_size_id = (sfr[0] >> 4) & 0x07; switch (flash_size_id) { case 0x01: unit_info.flash_size = 32; break; case 0x02: unit_info.flash_size = 64; break; case 0x03: unit_info.flash_size = (unit_info.ID == 0x2533) ? 96 : 128; break; case 0x04: unit_info.flash_size = 256; break; } if (small_unit) { if (flash_size_id == 0x01) unit_info.flash_size = 18; if (flash_size_id == 0x07) unit_info.flash_size = 32; } unit_info.flash_sizes.push_back(16);// unit_info.flash_sizes.push_back(32); unit_info.flash_sizes.push_back(64); unit_info.flash_sizes.push_back(96); unit_info.flash_sizes.push_back(128); unit_info.flash_sizes.push_back(256); ///unit_info.flash_size = 64;//// if (!small_unit) { unit_info.flash_page_size = (unit_info.ID == 0x2533) ? 1 : 2; unit_info.max_flash_size = (unit_info.ID == 0x2533) ? 96 : 256; unit_info.flags |= UnitInfo::SUPPORT_MAC_ADDRESS; unit_info.mac_address_count = 2; unit_info.mac_address_size = (unit_info.ID == 0x2540 || unit_info.ID == 0x2541) ? 6 : 8; } else { unit_info.flash_page_size = 1; unit_info.max_flash_size = 32; UnitCoreInfo reg_info(get_reg_info()); reg_info.write_block_size = 512; reg_info.verify_block_size = 512; reg_info.dma0_cfg_offset = 0x0200; set_reg_info(reg_info); } read_xdata_memory(0x6249, 1, sfr); unit_info.revision = sfr[0]; read_xdata_memory(0x624A, 1, sfr); unit_info.internal_ID = sfr[0]; unit_info_ = unit_info; } //============================================================================== void CC_253x_254x::read_info_page(ByteVector &info_page) { log_info("programmer, read info page"); size_t address = INFO_PAGE_OFFSET; size_t total_size = INFO_PAGE_SIZE; ByteVector data; while (total_size) { size_t count = std::min(XDATA_READ_CHUNK_SIZE, total_size); read_xdata_memory(address, count, data); info_page.insert(info_page.end(), data.begin(), data.end()); total_size -= count; address += count; } } //============================================================================== void CC_253x_254x::mac_address_read(size_t index, ByteVector &mac_address) { CHECK_PARAM(unit_info_.flags & UnitInfo::SUPPORT_MAC_ADDRESS); log_info("programmer, read mac address %u", index); if (index == 0) { size_t offset = (unit_info_.ID == 0x2540 || unit_info_.ID == 0x2541) ? 0x780E : 0x780C; read_xdata_memory(offset, unit_info_.mac_address_size, mac_address); } if (index == 1) { size_t offset = unit_info_.flash_size * 1024 - LOCK_DATA_SIZE - unit_info_.mac_address_size; flash_read_start(); flash_read_block(offset, unit_info_.mac_address_size, mac_address); flash_read_end(); } } //============================================================================== bool CC_253x_254x::erase_check_comleted() { log_info("programmer, check erase is completed"); uint8_t status = 0; read_debug_status(status); return !(status & DEBUG_STATUS_CHIP_ERASE_BUSY); } //============================================================================== void CC_253x_254x::flash_select_bank(uint_t bank) { log_info("programmer, set flash bank %u", bank); uint8_t command[] = { 0xBE, 0x57, 0x75, 0x9F, LOBYTE(bank) }; usb_device_.bulk_write(endpoint_out_, sizeof(command), &command[0]); } //============================================================================== void CC_253x_254x::flash_read_block(size_t offset, size_t size, ByteVector &data) { flash_read(offset, size, data); } //============================================================================== void CC_253x_254x::convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data) { ByteVector data(LOCK_DATA_SIZE, 0xFF); foreach (const String &s, qualifiers) { if (s == "debug") data[LOCK_DATA_SIZE - 1] &= ~0x80; else if (s == "pages" || s == "flash") { uint8_t bit = (data[LOCK_DATA_SIZE - 1] & 0x80); // save debug bit std::fill(data.begin(), data.end(), 0xFF); data[LOCK_DATA_SIZE - 1] &= (~0x80 | bit); // restore debug bit } else if (s.find("pages:") == 0) { BoolVector pages; read_range(s.substr(ARRAY_SIZE("pages:") - 1), pages, 0, MAX_PAGE_COUNT - 1); uint_t count = std::min(pages.size(), MAX_PAGE_COUNT); for (uint_t i = 0; i < count; i++) if (pages[i]) data[i / 8] &= ~(1 << (i % 8)); } else throw std::runtime_error("unknown lock qualifyer: " + s); } lock_data = data; } //============================================================================== bool CC_253x_254x::flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address) { if (!(unit_info_.flags & UnitInfo::SUPPORT_MAC_ADDRESS)) return false; DataSection section(mac_address_offset(), mac_address); sections.add_section(section, true); return true; } //============================================================================== bool CC_253x_254x::flash_image_embed_lock_data(DataSectionStore §ions, const ByteVector &lock_data) { DataSection section(lock_data_offset(), lock_data); sections.add_section(section, true); return true; } //============================================================================== uint_t CC_253x_254x::mac_address_offset() const { return unit_info_.flash_size * 1024 - LOCK_DATA_SIZE - unit_info_.mac_address_size; } //============================================================================== uint_t CC_253x_254x::lock_data_offset() const { return unit_info_.flash_size * 1024 - LOCK_DATA_SIZE; } //============================================================================== bool CC_253x_254x::config_write(const ByteVector &mac_address, const ByteVector &lock_data) { if (mac_address.empty() && lock_data.empty()) return true; const uint_t page_size = unit_info_.flash_page_size * 1024; const uint_t page_offset = unit_info_.flash_size * 1024 - page_size; ByteVector block; flash_read(page_offset, page_size, block); if (!empty_block(&block[0], block.size())) erase_page(page_offset); if (!mac_address.empty()) { CHECK_PARAM(mac_address.size() == unit_info_.mac_address_size); CHECK_PARAM(unit_info_.flags & UnitInfo::SUPPORT_MAC_ADDRESS); memcpy(&block[mac_address_offset() - page_offset], &mac_address[0], unit_info_.mac_address_size); } if (!lock_data.empty()) { CHECK_PARAM(lock_data.size() == LOCK_DATA_SIZE); memcpy(&block[lock_data_offset() - page_offset], &lock_data[0], LOCK_DATA_SIZE); } DataSectionStore store; store.add_section(DataSection(page_offset, block), true); write_flash_slow(store); ByteVector check_block; flash_read(page_offset, page_size, check_block); return memcmp(&check_block[0], &block[0], block.size()) == 0; } //============================================================================== void CC_253x_254x::flash_write(const DataSectionStore §ions) { if (unit_info_.ID == 0x2543 || unit_info_.ID == 0x2544 || unit_info_.ID == 0x2545) { write_flash_slow(sections); return; } // Buffers const uint16_t ADDR_BUF0 = 0x0000; // 1K const uint16_t ADDR_BUF1 = 0x0400; // 1K const uint16_t ADDR_DMA_DESC = 0x0800; // 32 bytes // DMA Channels const uint8_t CH_DBG_TO_BUF0 = 0x02; const uint8_t CH_DBG_TO_BUF1 = 0x04; const uint8_t CH_BUF0_TO_FLASH = 0x08; const uint8_t CH_BUF1_TO_FLASH = 0x10; const uint16_t PROG_BLOCK_SIZE = 1024; const uint8_t dma_desc[32] = { // Debug Interface -> Buffer 0 (Channel 1) HIBYTE(XREG_DBGDATA), // src[15:8] LOBYTE(XREG_DBGDATA), // src[7:0] HIBYTE(ADDR_BUF0), // dest[15:8] LOBYTE(ADDR_BUF0), // dest[7:0] HIBYTE(PROG_BLOCK_SIZE), LOBYTE(PROG_BLOCK_SIZE), 31, // trigger DBG_BW 0x11, // increment destination // Debug Interface -> Buffer 1 (Channel 2) HIBYTE(XREG_DBGDATA), // src[15:8] LOBYTE(XREG_DBGDATA), // src[7:0] HIBYTE(ADDR_BUF1), // dest[15:8] LOBYTE(ADDR_BUF1), // dest[7:0] HIBYTE(PROG_BLOCK_SIZE), LOBYTE(PROG_BLOCK_SIZE), 31, // trigger DBG_BW 0x11, // increment destination // Buffer 0 -> Flash controller (Channel 3) HIBYTE(ADDR_BUF0), // src[15:8] LOBYTE(ADDR_BUF0), // src[7:0] HIBYTE(XREG_FWDATA), // dest[15:8] LOBYTE(XREG_FWDATA), // dest[7:0] HIBYTE(PROG_BLOCK_SIZE), LOBYTE(PROG_BLOCK_SIZE), 18, // trigger FLASH 0x42, // increment source // Buffer 1 -> Flash controller (Channel 4) HIBYTE(ADDR_BUF1), // src[15:8] LOBYTE(ADDR_BUF1), // src[7:0] HIBYTE(XREG_FWDATA), // dest[15:8] LOBYTE(XREG_FWDATA), // dest[7:0] HIBYTE(PROG_BLOCK_SIZE), LOBYTE(PROG_BLOCK_SIZE), 18, // trigger FLASH 0x42 // increment source }; ByteVector xsfr; // Load dma descriptors write_xdata_memory(ADDR_DMA_DESC, dma_desc, sizeof(dma_desc)); // Set the pointer to the DMA descriptors write_xdata_memory(XREG_DMA1CFGL, LOBYTE(ADDR_DMA_DESC)); write_xdata_memory(XREG_DMA1CFGH, HIBYTE(ADDR_DMA_DESC)); write_xdata_memory(XREG_FADDRL, 0); write_xdata_memory(XREG_FADDRH, 0); ByteVector data; sections.create_image(FLASH_EMPTY_BYTE, data); data.resize(align_up(sections.upper_address(), PROG_BLOCK_SIZE), FLASH_EMPTY_BYTE); pw_.write_start(data.size()); uint8_t dbg_arm, flash_arm; for (size_t i = 0; i < (data .size() / PROG_BLOCK_SIZE); i++) { if ((i & 0x0001) == 0) { dbg_arm = CH_DBG_TO_BUF0; flash_arm = CH_BUF0_TO_FLASH; } else { dbg_arm = CH_DBG_TO_BUF1; flash_arm = CH_BUF1_TO_FLASH; } // transfer next buffer (first buffer when i == 0) write_xdata_memory(XREG_DMAARM, dbg_arm); ByteVector command; command.push_back(0xEE); command.push_back(0x84); command.push_back(0x00); command.insert(command.end(), &data[i * PROG_BLOCK_SIZE], &data[i * PROG_BLOCK_SIZE] + PROG_BLOCK_SIZE); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); // wait for write to finish while (read_xdata_memory(XREG_FCTL) & 0x80); write_xdata_memory(XREG_DMAARM, flash_arm); write_xdata_memory(XREG_FCTL, 0x06); pw_.write_progress(PROG_BLOCK_SIZE); } while (read_xdata_memory(XREG_FCTL) & FCTL_BUSY); // wait for the last buffer pw_.write_finish(); } cc-tool-0.27/src/programmer/cc_253x_254x.h000066400000000000000000000031131371037307000200440ustar00rootroot00000000000000/* * cc_253x_254x.h * * Created on: Aug 4, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_253X_254X_H_ #define _CC_253X_254X_H_ #include "cc_debug_interface.h" #include "cc_unit_driver.h" class CC_253x_254x : public CC_UnitDriver { public: virtual void supported_units(Unit_ID_List &units); virtual void find_unit_info(UnitInfo &info); virtual void read_info_page(ByteVector &info_page); virtual bool erase_check_comleted(); /// @param offset must be at page boundaries virtual void mac_address_read(size_t index, ByteVector &mac_address); virtual void flash_write(const DataSectionStore §ions); virtual bool config_write(const ByteVector &mac_address, const ByteVector &lock_data); virtual bool flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address); virtual bool flash_image_embed_lock_data(DataSectionStore §ions, const ByteVector &lock_data); virtual void convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data); CC_253x_254x(USB_Device &programmer, ProgressWatcher &pw); private: virtual void flash_read_block(size_t offset, size_t size, ByteVector &flash_data); // void flash_read_page(uint16_t address, ByteVector &flash_data); void flash_select_bank(uint_t bank); // void flash_read_start(); // void flash_read_end(); /// Return absolute flash offset where secondary mac address is stored uint_t mac_address_offset() const; /// Return absolute flash offset where lock data is stored uint_t lock_data_offset() const; }; #endif // !_CC_253X_2540_H_ cc-tool-0.27/src/programmer/cc_debug_interface.h000066400000000000000000000023601371037307000216720ustar00rootroot00000000000000/* * cc_debug_interface.h * * Created on: Jul 28, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_DEBUG_INTERFACE_H_ #define _CC_DEBUG_INTERFACE_H_ #include "common.h" const size_t CC_BREAKPOINT_COUNT = 4; const uint8_t DEBUG_STATUS_STACK_OVERFLOW = 0x01, DEBUG_STATUS_OSCILLATOR_STABLE = 0x02, DEBUG_STATUS_DEBUG_LOCKED = 0x04, DEBUG_STATUS_HALT_STATUS = 0x08, DEBUG_STATUS_PM_ACTIVE = 0x10, DEBUG_STATUS_CPU_HALTED = 0x20, DEBUG_STATUS_PCON_IDLE = 0x40, DEBUG_STATUS_CHIP_ERASE_BUSY = 0x80; const uint8_t DEBUG_CONFIG_SEL_FLASH_INFO_PAGE = 0x01, DEBUG_CONFIG_TIMER_SUSPEND = 0x02, DEBUG_CONFIG_DMA_PAUSE = 0x04, DEBUG_CONFIG_TIMERS_OFF = 0x08, DEBUG_CONFIG_SOFT_POWER_MODE = 0x20; const uint8_t DEBUG_COMMAND_CHIP_ERASE = 0x14, DEBUG_COMMAND_WR_CONFIG = 0x1D, DEBUG_COMMAND_RD_CONFIG = 0x24, DEBUG_COMMAND_GET_PC = 0x28, DEBUG_COMMAND_READ_STATUS = 0x34, DEBUG_COMMAND_SET_HW_BRKPNT = 0x3F, DEBUG_COMMAND_HALT = 0x44, DEBUG_COMMAND_RESUME = 0x4C, DEBUG_COMMAND_DEBUG_INSTR = 0x55, DEBUG_COMMAND_STEP_INSTR = 0x5C, DEBUG_COMMAND_GET_BM = 0x00,// ?? DEBUG_COMMAND_GET_CHIP_ID = 0x68, DEBUG_COMMAND_BURST_WRITE = 0x80; #endif // !_CC_DEBUG_INTERFACE_H_ cc-tool-0.27/src/programmer/cc_programmer.cpp000066400000000000000000000301141371037307000212700ustar00rootroot00000000000000/* * cc_programmer.cpp * * Created on: Aug 4, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "cc_programmer.h" #include "cc_251x_111x.h" #include "cc_253x_254x.h" #include "cc_243x.h" #include "log.h" const uint_t DEFAULT_TIMEOUT = 3000; const uint_t MAX_ERASE_TIME = 8000; const static USB_DeviceID DeviceTable[] = { { 0x0451, 0x16A2, 0x84, 0x04, "CC Debugger", USB_DeviceID::PROTOCOL_TI }, { 0x11A0, 0xDB20, 0x84, 0x04, "SmartRF04 Evaluation Board", USB_DeviceID::PROTOCOL_TI }, { 0x11A0, 0xEB20, 0x82, 0x02, "SmartRF04 Evaluation Board (Chinese)", USB_DeviceID::PROTOCOL_CHIPCON }, { 0x0451, 0x16A0, 0x84, 0x04, "SmartRF05 Evaluation Board", USB_DeviceID::PROTOCOL_TI }, }; //============================================================================== static void log_add_target_info(const UnitInfo &unit_info) { log_info("target, name: %s, chip ID: %02Xh, rev. %02Xh, flash: %u, ram: %u, flags: %02Xh", unit_info.name.c_str(), unit_info.internal_ID, unit_info.revision, unit_info.flash_size, unit_info.ram_size, unit_info.flags); } //============================================================================== static void log_add_programmer_info(const CC_ProgrammerInfo &info) { log_info("device, name: %s, ID: %s, version: %04Xh, revision: %04Xh", info.name.c_str(), info.debugger_id.c_str(), info.fw_version, info.fw_revision); } //============================================================================== CC_Programmer::CC_Programmer() { usb_device_.set_transfer_timeout(DEFAULT_TIMEOUT); unit_drviers_.push_back(CC_UnitDriverPtr(new CC_253x_254x(usb_device_, pw_))); unit_drviers_.push_back(CC_UnitDriverPtr(new CC_251x_111x(usb_device_, pw_))); unit_drviers_.push_back(CC_UnitDriverPtr(new CC_243x(usb_device_, pw_))); } //============================================================================== USB_DeviceIDVector CC_Programmer::supported_devices() const { USB_DeviceIDVector result; foreach (const USB_DeviceID &item, DeviceTable) result.push_back(item); return result; } //============================================================================== StringVector CC_Programmer::supported_unit_names() const { StringVector names; foreach (const CC_UnitDriverPtr &item, unit_drviers_) { Unit_ID_List units; item->supported_units(units); foreach (Unit_ID &unit, units) names.push_back(unit.name); } return names; } //============================================================================== bool CC_Programmer::set_debug_interface_speed(CC_Programmer::InterfaceSpeed speed) { log_info("programmer, set debug interface speed %u", speed); if (!opened()) return false; const uint8_t USB_SET_DEBUG_INTERFACE_SPEED = 0xCF; uint16_t value = (speed == CC_Programmer::IS_FAST) ? 0 : 1; usb_device_.control_write(LIBUSB_REQUEST_TYPE_VENDOR, USB_SET_DEBUG_INTERFACE_SPEED, value, 0, NULL, 0); return true; } //============================================================================== bool CC_Programmer::unit_set_flash_size(uint_t flash_size) { return driver_->set_flash_size(flash_size); } //============================================================================== bool CC_Programmer::programmer_info(CC_ProgrammerInfo &info) { if (opened()) { info = programmer_info_; return true; } return false; } //============================================================================== void CC_Programmer::init_device() { if (programmer_info_.usb_device.protocol == USB_DeviceID::PROTOCOL_CHIPCON) usb_device_.reset_device(); usb_device_.set_configuration(1); usb_device_.claim_interface(0); request_device_info(); } //============================================================================== CC_Programmer::OpenResult CC_Programmer::open(uint_t bus, uint_t device) { if (!usb_device_.open_by_address(bus, device)) return OR_NOT_FOUND; libusb_device_descriptor descriptor; usb_device_.device_decriptor(descriptor); foreach (const USB_DeviceID &item, DeviceTable) { if (descriptor.idProduct == item.product_id && descriptor.idVendor == item.vendor_id) { programmer_info_.usb_device = item; init_device(); return OR_OK; } } return OR_NOT_SUPPORTED; } //============================================================================== CC_Programmer::OpenResult CC_Programmer::open() { foreach (const USB_DeviceID &item, DeviceTable) { if (usb_device_.open_by_vid_pid(item.vendor_id, item.product_id)) { programmer_info_.usb_device = item; break; } } if (!usb_device_.opened()) return OR_NOT_FOUND; init_device(); return OR_OK; } //============================================================================== void CC_Programmer::close() { usb_device_.close(); } //============================================================================== bool CC_Programmer::opened() const { return usb_device_.opened(); } //============================================================================== void CC_Programmer::request_device_info() { libusb_device_descriptor device_descriptor; usb_device_.device_decriptor(device_descriptor); char DID[16]; sprintf(DID, "%02X%02X", device_descriptor.bcdDevice >> 8, device_descriptor.bcdDevice & 0xFF); programmer_info_.debugger_id = DID; if (device_descriptor.iProduct > 0) usb_device_.string_descriptor_ascii(device_descriptor.iProduct, programmer_info_.name); else { foreach (const USB_DeviceID &item, DeviceTable) { if (device_descriptor.idProduct == item.product_id && device_descriptor.idVendor == item.vendor_id) { programmer_info_.name = item.description; break; } } } const uint8_t USB_REQUEST_GET_STATE = 0xC0; log_info("programmer, request device state"); uint8_t info[8]; usb_device_.control_read(LIBUSB_REQUEST_TYPE_VENDOR, USB_REQUEST_GET_STATE, 0, 0, info, 8); programmer_info_.fw_version = info[2] | info[3] << 8; programmer_info_.fw_revision = info[4] | info[5] << 8; unit_info_.ID = info[0] | info[1] << 8; foreach (CC_UnitDriverPtr &driver, unit_drviers_) { Unit_ID_List units; driver->supported_units(units); foreach (Unit_ID &unit, units) { if (unit.ID == unit_info_.ID) { unit_info_.name = unit.name; driver_ = driver; break; } } } if (!driver_ && unit_info_.ID > 0) { std::swap(info[0], info[1]); unit_info_.name = "CC" + binary_to_hex(info, 2, ""); } if (driver_) driver_->set_programmer_ID(programmer_info_.usb_device); log_add_programmer_info(programmer_info_); } //============================================================================== void CC_Programmer::unit_status(String &name, bool &supported) const { name = unit_info_.name; supported = (driver_ != NULL); } //============================================================================== void CC_Programmer::unit_close() { driver_->reset(false); } //============================================================================== void CC_Programmer::enter_debug_mode() { log_info("programmer, enter debug mode"); const uint8_t USB_PREPARE_DEBUG_MODE = 0xC5; usb_device_.control_write(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, USB_PREPARE_DEBUG_MODE, 0, 0, NULL, 0); const uint8_t USB_SET_CHIP_INFO = 0xC8; const size_t command_size = programmer_info_.usb_device.protocol == USB_DeviceID::PROTOCOL_TI ? 0x30 : 0x20; ByteVector command(command_size, ' '); memcpy(&command[0x00], unit_info_.name.c_str(), unit_info_.name.size()); memcpy(&command[0x10], "DID:", 4); memcpy(&command[0x15], programmer_info_.debugger_id.c_str(), programmer_info_.debugger_id.size()); usb_device_.control_write(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, USB_SET_CHIP_INFO, 1, 0, &command[0], command.size()); } //============================================================================== bool CC_Programmer::unit_locked() { log_info("programmer, check if unit locked"); uint8_t status = 0; driver_->read_debug_status(status); return (status & DEBUG_STATUS_DEBUG_LOCKED); } //============================================================================== bool CC_Programmer::unit_connect(UnitInfo &info) { log_info("programmer, connect target"); enter_debug_mode(); driver_->reset(true); uint8_t status = 0; driver_->read_debug_status(status); if ((status & DEBUG_STATUS_DEBUG_LOCKED)) { log_info("programmer, target is locked"); return true; } if (!(status & DEBUG_STATUS_CPU_HALTED)) { log_info("programmer, halt failed"); return false; } driver_->write_debug_config(DEBUG_CONFIG_TIMER_SUSPEND | DEBUG_CONFIG_SOFT_POWER_MODE); driver_->find_unit_info(unit_info_); log_add_target_info(unit_info_); info = unit_info_; return true; } //============================================================================== bool CC_Programmer::unit_reset() { driver_->reset(false); return true; } //============================================================================== bool CC_Programmer::unit_erase() { driver_->erase(); uint_t erase_timer = get_tick_count(); do { if (driver_->erase_check_comleted()) return true; usleep(500 * 1000); } while ((get_tick_count() - erase_timer) <= MAX_ERASE_TIME); return false; // erase timeout } //============================================================================== void CC_Programmer::unit_read_info_page(ByteVector &info_page) { pw_.enable(false); driver_->read_info_page(info_page); } //============================================================================== void CC_Programmer::unit_mac_address_read(size_t index, ByteVector &mac_address) { pw_.enable(false); driver_->mac_address_read(index, mac_address); } //============================================================================== bool CC_Programmer::unit_config_write(ByteVector &mac_address, ByteVector &lock_data) { pw_.enable(false); return driver_->config_write(mac_address, lock_data); } //============================================================================== bool CC_Programmer::flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address) { return driver_->flash_image_embed_mac_address(sections, mac_address); } //============================================================================== bool CC_Programmer::flash_image_embed_lock_data(DataSectionStore §ions, const ByteVector &lock_data) { return driver_->flash_image_embed_lock_data(sections, lock_data); } //============================================================================== uint_t CC_Programmer::unit_lock_data_size() const { return driver_->lock_data_size(); } //============================================================================== void CC_Programmer::unit_convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data) { driver_->convert_lock_data(qualifiers, lock_data); } //============================================================================== void CC_Programmer::unit_flash_read(ByteVector &flash_data) { pw_.enable(true); pw_.read_start(unit_info_.actual_flash_size()); driver_->flash_read_start(); driver_->flash_read_block(0, unit_info_.actual_flash_size(), flash_data); driver_->flash_read_end(); pw_.read_finish(); } //============================================================================== bool CC_Programmer::unit_flash_verify(const DataSectionStore §ions, CC_Programmer::VerifyMethod method) { log_info("programmer, verify flash, %u", method); pw_.enable(true); if (method == VM_BY_CRC) return driver_->flash_verify_by_crc(sections); return driver_->flash_verify_by_read(sections); } //============================================================================== void CC_Programmer::unit_flash_write(const DataSectionStore §ions) { pw_.enable(true); driver_->flash_write(sections); } //============================================================================== void CC_Programmer::do_on_flash_read_progress( const ProgressWatcher::OnProgress::slot_type &slot) { pw_.do_on_read_progress(slot); } //============================================================================== void CC_Programmer::do_on_flash_write_progress( const ProgressWatcher::OnProgress::slot_type &slot) { pw_.do_on_write_progress(slot); } cc-tool-0.27/src/programmer/cc_programmer.h000066400000000000000000000053211371037307000207370ustar00rootroot00000000000000/* * cc_programmer.h * * Created on: Aug 2, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_PROGRAMMER_H_ #define _CC_PROGRAMMER_H_ #include "cc_unit_driver.h" #include "usb/usb_device.h" #include "data/data_section_store.h" struct USB_DeviceID { enum { PROTOCOL_TI, PROTOCOL_CHIPCON }; uint16_t vendor_id; uint16_t product_id; uint8_t endpoint_in; uint8_t endpoint_out; char description[256]; uint_t protocol; }; struct CC_ProgrammerInfo { String name; String debugger_id; // 4 unique digits uint16_t fw_version; uint16_t fw_revision; USB_DeviceID usb_device; }; struct CC_Breakpoint { size_t number; size_t address; }; typedef std::vector CC_BreakpointVector; typedef std::vector USB_DeviceIDVector; /// class CC_Programmer : boost::noncopyable { public: enum OpenResult { OR_OK, OR_NOT_FOUND, OR_NOT_SUPPORTED }; OpenResult open(); OpenResult open(uint_t bus, uint_t device); bool opened() const; void close(); bool programmer_info(CC_ProgrammerInfo &info); StringVector supported_unit_names() const; USB_DeviceIDVector supported_devices() const; enum InterfaceSpeed { IS_SLOW, IS_FAST }; bool set_debug_interface_speed(InterfaceSpeed speed); bool unit_set_flash_size(uint_t flash_size); void unit_status(String &name, bool &supported) const; bool unit_connect(UnitInfo &info); void unit_close(); bool unit_reset(); bool unit_locked(); bool unit_erase(); void unit_read_info_page(ByteVector &info_page); void unit_mac_address_read(size_t index, ByteVector &mac_address); void unit_flash_read(ByteVector &flash_data); void unit_flash_write(const DataSectionStore §ions); enum VerifyMethod { VM_BY_CRC, VM_BY_READ }; bool unit_flash_verify(const DataSectionStore §ions, VerifyMethod method); bool unit_config_write(ByteVector &mac_address, ByteVector &lock_data); void unit_convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data); uint_t unit_lock_data_size() const; bool flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address); bool flash_image_embed_lock_data(DataSectionStore §ions, const ByteVector &lock_data); void do_on_flash_read_progress(const ProgressWatcher::OnProgress::slot_type&); void do_on_flash_write_progress(const ProgressWatcher::OnProgress::slot_type&); CC_Programmer(); private: void request_device_info(); void enter_debug_mode(); void init_device(); CC_ProgrammerInfo programmer_info_; UnitInfo unit_info_; USB_Device usb_device_; CC_UnitDriverPtrList unit_drviers_; CC_UnitDriverPtr driver_; ProgressWatcher pw_; //CC_Breakpoint bps_[CC_BREAKPOINT_COUNT]; }; #endif // !_CC_PROGRAMMER_H_ cc-tool-0.27/src/programmer/cc_unit_driver.cpp000066400000000000000000000502111371037307000214470ustar00rootroot00000000000000/* * cc_unit_driver.cpp * * Created on: Aug 2, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include #include "cc_unit_driver.h" #include "cc_programmer.h" #include "log.h" #include "cc_debug_interface.h" #include "data/binary_file.h" // remove #include "data/hex_file.h" // remove typedef boost::crc_optimal<16, 0x8005, 0xFFFF, 0, false, false> CrcCalculator; const size_t MAX_EMPTY_BLOCK_SIZE = FLASH_BANK_SIZE; static uint8_t empty_block_[MAX_EMPTY_BLOCK_SIZE]; //============================================================================== CC_UnitDriver::CC_UnitDriver(USB_Device &programmer, ProgressWatcher &pw) : usb_device_(programmer), pw_(pw), endpoint_in_(0), endpoint_out_(0) { memset(empty_block_, FLASH_EMPTY_BYTE, FLASH_BANK_SIZE); } //============================================================================== void CC_UnitDriver::set_programmer_ID(const USB_DeviceID& programmer_ID) { endpoint_in_ = programmer_ID.endpoint_in; endpoint_out_ = programmer_ID.endpoint_out; } //============================================================================== bool CC_UnitDriver::set_flash_size(uint_t flash_size) { bool found = std::find( unit_info_.flash_sizes.begin(), unit_info_.flash_sizes.end(), flash_size) != unit_info_.flash_sizes.end(); if (!unit_info_.flash_size && found) { unit_info_.flash_size = flash_size; return true; } return false; } //============================================================================== void CC_UnitDriver::reset(bool debug_mode) { log_info("programmer, reset target, debug mode: %u", debug_mode); const uint8_t USB_REQUEST_RESET = 0xC9; uint16_t index = debug_mode ? 1 : 0; usb_device_.control_write(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, USB_REQUEST_RESET, 0, index, NULL, 0); } //============================================================================== void CC_UnitDriver::read_debug_status(uint8_t &status) { log_info("programmer, read debug status"); uint8_t command[] = { 0x1F, DEBUG_COMMAND_READ_STATUS }; status = 0; usb_device_.bulk_write(endpoint_out_, sizeof(command), command); usb_device_.bulk_read(endpoint_in_, 1, &status); log_info("programmer, debug status, %02Xh", status); } //============================================================================== void CC_UnitDriver::read_debug_config(uint8_t &config) { log_info("programmer, read debug config"); uint8_t command[] = { 0x1F, DEBUG_COMMAND_RD_CONFIG }; usb_device_.bulk_write(endpoint_out_, sizeof(command), command); usb_device_.bulk_read(endpoint_in_, 1, &config); log_info("programmer, debug config, %02Xh", config); } //============================================================================== void CC_UnitDriver::write_debug_config(uint8_t config) { log_info("programmer, write debug config, %02Xh", config); uint8_t command[] = { 0x4C, DEBUG_COMMAND_WR_CONFIG, config }; usb_device_.bulk_write(endpoint_out_, sizeof(command), command); } //============================================================================== bool CC_UnitDriver::erase_page(uint_t page_offset) { page_offset /= reg_info_.flash_word_size; write_xdata_memory(reg_info_.faddrl, 0); write_xdata_memory(reg_info_.faddrh, HIBYTE(page_offset)); // erase write_xdata_memory(reg_info_.fctl, FCTL_ERASE); // wait for write to finish uint8_t reg; while ((reg = read_xdata_memory(reg_info_.fctl)) & FCTL_BUSY); return !(reg & FCTL_ABORT); } //============================================================================== void CC_UnitDriver::erase() { log_info("programmer, erase"); uint8_t command[] = { 0x1C, DEBUG_COMMAND_CHIP_ERASE }; usb_device_.bulk_write(endpoint_out_, sizeof(command), command); } //============================================================================== void CC_UnitDriver::write_sfr(uint8_t address, uint8_t value) { log_info("write sfr at %02Xh, value: %02Xh", address, value); uint8_t header[] = { 0x40, 0x55, 0x00, }; uint8_t mov_a_direct[] = { 0xBE, 0x57, 0x75, address, value }; uint8_t footer[] = { 0x90, 0x56, 0x74 }; ByteVector command; vector_append(command, header, sizeof(header)); vector_append(command, mov_a_direct, sizeof(mov_a_direct)); vector_append(command, footer, sizeof(footer)); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); } //============================================================================== void CC_UnitDriver::read_sfr(uint8_t address, uint8_t &value) { log_info("programmer, read sfr at %02Xh", address); uint8_t header[] = { 0x40, 0x55, 0x00, }; uint8_t mov_a_direct[] = { 0x7F, 0x56, 0xE5, address }; uint8_t footer[] = { 0x90, 0x56, 0x74 }; ByteVector command; vector_append(command, header, sizeof(header)); vector_append(command, mov_a_direct, sizeof(mov_a_direct)); vector_append(command, footer, sizeof(footer)); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); usb_device_.bulk_read(endpoint_in_, 1, &value); log_info("programmer, sfr value: %02Xh", value); } //============================================================================== uint8_t CC_UnitDriver::read_xdata_memory(uint16_t address) { ByteVector data; read_xdata_memory(address, 1, data); return data[0]; } //============================================================================== void CC_UnitDriver::read_xdata_memory(uint16_t address, size_t count, ByteVector &data) { log_info("programmer, read xdata memory at %04Xh, count: %u", address, count); uint8_t header[] = { 0x40, 0x55, 0x00, 0x72, 0x56, 0xE5, 0x92, 0xBE, 0x57, 0x75, 0x92, 0x00, 0x74, 0x56, 0xE5, 0x83, 0x76, 0x56, 0xE5, 0x82 }; uint8_t footer[] = { 0xD4, 0x57, 0x90, 0xC2, 0x57, 0x75, 0x92, 0x90, 0x56, 0x74 }; uint8_t load_dtpr[] = { 0xBE, 0x57, 0x90, 0x00, 0x00 }; uint8_t mov_a_dtpr[] = { 0x4E, 0x55, 0xE0 }; uint8_t inc_dtpr[] = { 0x5E, 0x55, 0xA3 }; ByteVector command; vector_append(command, header, sizeof(header)); load_dtpr[sizeof(load_dtpr) - 1] = address; load_dtpr[sizeof(load_dtpr) - 2] = address >> 8; vector_append(command, load_dtpr, sizeof(load_dtpr)); for (size_t i = 0; i < count; i++) { if (i == (count - 1) || !((i + 1) % 64)) mov_a_dtpr[0] |= 1; else mov_a_dtpr[0] &= ~1; vector_append(command, mov_a_dtpr, sizeof(mov_a_dtpr)); vector_append(command, inc_dtpr, sizeof(inc_dtpr)); } vector_append(command, footer, sizeof(footer)); data.resize(count); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); usb_device_.bulk_read(endpoint_in_, count, &data[0]); log_info("programmer, read xdata memory, data: %s", binary_to_hex(&data[0], count, " ").c_str()); } //============================================================================== bool CC_UnitDriver::flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address) { return false; } //============================================================================== bool CC_UnitDriver::flash_image_embed_lock_data(DataSectionStore §ions, const ByteVector &lock_data) { return false; } //============================================================================== void CC_UnitDriver::read_info_page(ByteVector &info_page) { } //============================================================================== void CC_UnitDriver::mac_address_read(size_t index, ByteVector &mac_address) { } //============================================================================== void CC_UnitDriver::write_xdata_memory(uint16_t address, uint8_t data) { write_xdata_memory(address, &data, 1); } //============================================================================== void CC_UnitDriver::write_xdata_memory(uint16_t address, const ByteVector &data) { write_xdata_memory(address, &data[0], data.size()); } //============================================================================== void CC_UnitDriver::write_xdata_memory(uint16_t address, const uint8_t data[], size_t size) { log_info("programmer, write xdata memory at %04Xh, count: %u", address, size); uint8_t header[] = { 0x40, 0x55, 0x00, 0x72, 0x56, 0xE5, 0x92, 0xBE, 0x57, 0x75, 0x92, 0x00, 0x74, 0x56, 0xE5, 0x83, 0x76, 0x56, 0xE5, 0x82 }; uint8_t footer[] = { 0xD4, 0x57, 0x90, 0xC2, 0x57, 0x75, 0x92, 0x90, 0x56, 0x74 }; uint8_t load_dtpr[] = { 0xBE, 0x57, 0x90, HIBYTE(address), LOBYTE(address) }; uint8_t mov_a_data[] = { 0x8E, 0x56, 0x74, 0x00 }; uint8_t mov_dtpr_a[] = { 0x5E, 0x55, 0xF0 }; uint8_t inc_dtpr[] = { 0x5E, 0x55, 0xA3 }; ByteVector command; vector_append(command, header, sizeof(header)); vector_append(command, load_dtpr, sizeof(load_dtpr)); for (size_t i = 0; i < size; i++) { mov_a_data[3] = data[i]; vector_append(command, mov_a_data, sizeof(mov_a_data)); vector_append(command, mov_dtpr_a, sizeof(mov_dtpr_a)); vector_append(command, inc_dtpr, sizeof(inc_dtpr)); } vector_append(command, footer, sizeof(footer)); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); } //============================================================================== void CC_UnitDriver::select_info_page_flash(bool select_info_pages) { uint8_t config = 0; read_debug_config(config); if (select_info_pages) config |= DEBUG_CONFIG_SEL_FLASH_INFO_PAGE; else config &= ~DEBUG_CONFIG_SEL_FLASH_INFO_PAGE; write_debug_config(config); } //============================================================================== bool CC_UnitDriver::flash_verify_by_read(const DataSectionStore §ion_store) { ByteVector data; bool result = true; pw_.read_start(section_store.actual_size()); flash_read_start(); foreach (const DataSection &item, section_store.sections()) { flash_read_block(item.address, item.size(), data); if (memcmp(&data[0], &item.data[0], item.size())) { //binary_file_save("vr.bin", data); result = false; break; } data.clear(); } flash_read_end(); pw_.read_finish(); return result; } //============================================================================== bool CC_UnitDriver::flash_verify_by_crc(const DataSectionStore §ion_store) { // Channel 0: Flash mapped to Xdata -> CRC shift register uint8_t dma_desc[8] = { HIBYTE(reg_info_.xbank_offset), // src[15:8] LOBYTE(reg_info_.xbank_offset), // src[7:0] HIBYTE(reg_info_.rndh), // dest[15:8] LOBYTE(reg_info_.rndh), // dest[7:0] HIBYTE(reg_info_.verify_block_size),// block size[15:8] LOBYTE(reg_info_.verify_block_size),// block size[7:0] 0x20, // no trigger event, block mode 0x42, // increment source }; write_xdata_memory(reg_info_.dma_arm, 0x00); // set the pointer to the DMA descriptors write_xdata_memory(reg_info_.dma0_cfgl, LOBYTE(reg_info_.dma0_cfg_offset)); write_xdata_memory(reg_info_.dma0_cfgh, HIBYTE(reg_info_.dma0_cfg_offset)); size_t flash_bank = 0xFF; // correct flash bank will be set later pw_.read_start(section_store.actual_size()); foreach (const DataSection §ion, section_store.sections()) { size_t section_offset = section.address; size_t total_size = section.size(); size_t bank_offset = section_offset % FLASH_BANK_SIZE; while (total_size) { size_t count = std::min(total_size, reg_info_.verify_block_size); size_t flash_bank_0 = section_offset / FLASH_BANK_SIZE; size_t flash_bank_1 = (section_offset + count) / FLASH_BANK_SIZE; if (flash_bank_0 != flash_bank_1) count = FLASH_BANK_SIZE - (section_offset % FLASH_BANK_SIZE); if (flash_bank != flash_bank_0) { flash_bank = flash_bank_0; if (reg_info_.memctr) write_xdata_memory(reg_info_.memctr, flash_bank); bank_offset = section_offset % FLASH_BANK_SIZE; } dma_desc[0] = HIBYTE(bank_offset + reg_info_.xbank_offset); dma_desc[1] = LOBYTE(bank_offset + reg_info_.xbank_offset); dma_desc[4] = HIBYTE(count); dma_desc[5] = LOBYTE(count); write_xdata_memory(reg_info_.dma0_cfg_offset, dma_desc, sizeof(dma_desc)); CrcCalculator crc_calc; crc_calc.process_bytes(§ion.data[section.size() - total_size], count); if (calc_block_crc() != crc_calc.checksum()) return false; total_size -= count; section_offset += count; bank_offset += count; pw_.read_progress(count); } } pw_.read_finish(); return true; } //============================================================================== uint16_t CC_UnitDriver::calc_block_crc() { write_xdata_memory(reg_info_.rndl, 0xFF); write_xdata_memory(reg_info_.rndl, 0xFF); write_xdata_memory(reg_info_.dma_arm, 0x01); write_xdata_memory(reg_info_.dma_req, 0x01); while (!(read_xdata_memory(reg_info_.dma_irq) & 0x01)); ByteVector xsfr; read_xdata_memory(reg_info_.rndl, 2, xsfr); return xsfr[0] | (xsfr[1] << 8); } //============================================================================== static void create_read_proc(size_t count, ByteVector &proc) { uint8_t clr_a[] = { 0x5E, 0x55, 0xE4 }; uint8_t mov_c_a_dptr_a[]= { 0x4E, 0x55, 0x93 }; uint8_t inc_dptr[] = { 0x5E, 0x55, 0xA3 }; proc.clear(); for (size_t i = 0; i < count; i++) { vector_append(proc, clr_a, sizeof(clr_a)); if (!((i + 1) % 64) || i == (count - 1)) mov_c_a_dptr_a[0] |= 0x01; vector_append(proc, mov_c_a_dptr_a, sizeof(mov_c_a_dptr_a)); mov_c_a_dptr_a[0] &= ~0x01; vector_append(proc, inc_dptr, sizeof(inc_dptr)); } } //============================================================================== void CC_UnitDriver::flash_read_near(uint16_t address, size_t size, ByteVector &data) { const uint8_t load_dtpr[] = { 0xBE, 0x57, 0x90, HIBYTE(address), LOBYTE(address) }; usb_device_.bulk_write(endpoint_out_, sizeof(load_dtpr), load_dtpr); size_t offset = data.size(); data.resize(offset + size, FLASH_EMPTY_BYTE); ByteVector command; for (size_t i = 0; i < size / FLASH_READ_CHUNK_SIZE; i++) { if (command.empty()) create_read_proc(FLASH_READ_CHUNK_SIZE, command); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); usb_device_.bulk_read(endpoint_in_, FLASH_READ_CHUNK_SIZE, &data[offset]); offset += FLASH_READ_CHUNK_SIZE; pw_.read_progress(FLASH_READ_CHUNK_SIZE); } if ((size % FLASH_READ_CHUNK_SIZE)) { create_read_proc(size % FLASH_READ_CHUNK_SIZE, command); usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]); usb_device_.bulk_read(endpoint_in_, size - offset, &data[offset]); pw_.read_progress(size - offset); } } //============================================================================== void CC_UnitDriver::flash_read(size_t offset, size_t size, ByteVector &flash_data) { uint8_t flash_bank = 0xFF; while (size) { size_t bank_offset = offset % FLASH_BANK_SIZE; size_t count = std::min(size, (size_t)0x8000); uint8_t flash_bank_0 = offset / FLASH_BANK_SIZE; uint8_t flash_bank_1 = (offset + count) / FLASH_BANK_SIZE; if (flash_bank_0 != flash_bank_1) size_t count = ((offset + count) % FLASH_BANK_SIZE); if (flash_bank != flash_bank_0) { flash_bank = flash_bank_0; write_xdata_memory(reg_info_.fmap, flash_bank); bank_offset = offset % FLASH_BANK_SIZE; } flash_read_near(bank_offset + reg_info_.xbank_offset, count, flash_data); size -= count; offset += count; } } //============================================================================== void CC_UnitDriver::flash_read_start() { const uint8_t USB_PREPARE = 0xC6; uint8_t byte = 0; usb_device_.control_read(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN, USB_PREPARE, 0, 0, &byte, 1); //reset(true); // if write and lock verifing will fail after reset uint8_t header[] = { 0x40, 0x55, 0x00, 0x72, 0x56, 0xE5, 0xD0, 0x74, 0x56, 0xE5, 0x92, 0xBE, 0x57, 0x75, 0x92, 0x00, 0x76, 0x56, 0xE5, 0x83, 0x78, 0x56, 0xE5, 0x82, 0x7A, 0x56, 0xE5, 0x9F }; usb_device_.bulk_write(endpoint_out_, sizeof(header), header); } //============================================================================== void CC_UnitDriver::flash_read_end() { uint8_t command[] = { 0xCA, 0x57, 0x75, 0x9F, 0xD6, 0x57, 0x90, 0xC4, 0x57, 0x75, 0x92, 0xC2, 0x57, 0x75, 0xD0, 0x90, 0x56, 0x74 }; usb_device_.bulk_write(endpoint_out_, sizeof(command), command); } //============================================================================== void CC_UnitDriver::write_lock_to_info_page(uint8_t lock_byte) { select_info_page_flash(true); ByteVector data; data.push_back(0xFF); data.push_back(lock_byte); DataSectionStore store; store.add_section(DataSection(0, data), true); write_flash_slow(store); select_info_page_flash(false); } //============================================================================== uint_t CC_UnitDriver::lock_data_size() const { return reg_info_.lock_size; } //============================================================================== UnitCoreInfo CC_UnitDriver::get_reg_info() { return reg_info_; } //============================================================================== void CC_UnitDriver::set_reg_info(const UnitCoreInfo ®_info) { reg_info_ = reg_info; } //============================================================================== bool CC_UnitDriver::empty_block(const uint8_t* data, size_t size) { if (size <= MAX_EMPTY_BLOCK_SIZE) return memcmp(data, empty_block_, size) == 0; ByteVector empty_block; empty_block.resize(size, FLASH_EMPTY_BYTE); return memcmp(data, &empty_block[0], size) == 0; } //============================================================================== void CC_UnitDriver::convert_lock_data_std_set( const StringVector& qualifiers, const ByteVector& lock_sizes, ByteVector& lock_data) { ByteVector data(1, 0x1F); foreach (const String &item, qualifiers) { if (item == "debug") data[0] &= ~1; else if (item == "boot") data[0] &= ~0x10; else if (item == "flash" || item == "pages") data[0] &= ~0x0E; else if (item.find("flash:") == 0) { uint_t size = 0; String arg = item.substr(ARRAY_SIZE("flash:") - 1); if (!string_to_number(arg, size)) throw std::runtime_error("incorrect flash size value"); ByteVector::const_iterator it = std::find( lock_sizes.begin(), lock_sizes.end(), size); if (it == lock_sizes.end()) throw std::runtime_error("target unsupport flash size " + arg); uint8_t index = (uint8_t)(it - lock_sizes.begin()); data[0] &= ~(7 << 1); // clear out prev lock size data data[0] |= (~index & 0x07) << 1; } else throw std::runtime_error("unknown lock qualifyer: " + item); } lock_data = data; } //============================================================================== void CC_UnitDriver::write_flash_slow(const DataSectionStore §ion_store) { const size_t WRITE_BLOCK_SIZE = reg_info_.write_block_size; // Channel 0: Xdata buffer -> Flash controller uint8_t dma_desc[8] = { HIBYTE(reg_info_.dma_data_offset),// src[15:8] LOBYTE(reg_info_.dma_data_offset),// src[7:0] HIBYTE(reg_info_.fwdata), // dest[15:8] LOBYTE(reg_info_.fwdata), // dest[7:0] HIBYTE(WRITE_BLOCK_SIZE), // block size[15:8] LOBYTE(WRITE_BLOCK_SIZE), // block size[7:0] 18, // trigger FLASH 0x42 // increment source }; // Load dma descriptors write_xdata_memory(reg_info_.dma0_cfg_offset, dma_desc, sizeof(dma_desc)); // Set the pointer to the DMA descriptors write_xdata_memory(reg_info_.dma0_cfgl, LOBYTE(reg_info_.dma0_cfg_offset)); write_xdata_memory(reg_info_.dma0_cfgh, HIBYTE(reg_info_.dma0_cfg_offset)); size_t faddr = (size_t)-1; ByteVector data; section_store.create_image(FLASH_EMPTY_BYTE, data); data.resize(align_up(section_store.upper_address(), WRITE_BLOCK_SIZE), FLASH_EMPTY_BYTE); pw_.write_start(data.size()); for (size_t i = 0; i < (data.size() / WRITE_BLOCK_SIZE); i++) { pw_.write_progress(WRITE_BLOCK_SIZE); size_t offset = WRITE_BLOCK_SIZE * i; if (empty_block(&data[offset], WRITE_BLOCK_SIZE)) continue; size_t next_faddr = offset / reg_info_.flash_word_size; if (next_faddr != faddr) { write_xdata_memory(reg_info_.faddrl, LOBYTE(next_faddr)); write_xdata_memory(reg_info_.faddrh, HIBYTE(next_faddr)); faddr = next_faddr + WRITE_BLOCK_SIZE / reg_info_.flash_word_size; } write_xdata_memory(reg_info_.dma_data_offset, &data[offset], WRITE_BLOCK_SIZE); write_xdata_memory(reg_info_.dma_arm, 0x01); write_xdata_memory(reg_info_.fctl, reg_info_.fctl_write); while ((read_xdata_memory(reg_info_.fctl) & FCTL_BUSY)); } pw_.write_finish(); } cc-tool-0.27/src/programmer/cc_unit_driver.h000066400000000000000000000121321371037307000211140ustar00rootroot00000000000000/* * cc_unit_driver.h * * Created on: Aug 4, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_UNIT_DRIVER_H_ #define _CC_UNIT_DRIVER_H_ #include "data/data_section_store.h" #include "data/progress_watcher.h" #include "usb/usb_device.h" #include "cc_unit_info.h" const size_t FLASH_EMPTY_BYTE = 0xFF; const size_t XDATA_READ_CHUNK_SIZE = 128; const size_t FLASH_READ_CHUNK_SIZE = 128; const size_t FLASH_BANK_SIZE = 1024 * 32; const size_t FLASH_MAPPED_BANK_OFFSET = 1024 * 32; const uint8_t FCTL_BUSY = 0x80; const uint8_t FCTL_ABORT = 0x20; const uint8_t FCTL_ERASE = 0x01; struct USB_DeviceID; class CC_UnitDriver : boost::noncopyable { public: virtual void supported_units(Unit_ID_List &units) = 0; virtual void find_unit_info(UnitInfo &info) = 0; virtual void read_info_page(ByteVector &info_page); /// Read mac address /// @param index 0 - primary address, 1 - secondary address (if any) virtual void mac_address_read(size_t index, ByteVector &mac_address); /// Write and verify lock data and/or mac address. If field is empty /// it wont be written. /// @return false if varification after write failed virtual bool config_write(const ByteVector &mac_address, const ByteVector &lock_data) = 0; /// Integrate mac address into flash image /// @return true if target store mac address in flash virtual bool flash_image_embed_mac_address(DataSectionStore §ions, const ByteVector &mac_address); /// Integrate lock data into flash image /// @return true if target store lock data in flash virtual bool flash_image_embed_lock_data(DataSectionStore §ions, const ByteVector &lock_data); /// Convert list of string qulifiers like 'debug', 'pages:xx' into lock data virtual void convert_lock_data(const StringVector& qualifiers, ByteVector& lock_data) = 0; /// Erase flash completely. Operation is asynchronious, virtual void erase(); virtual bool erase_check_comleted() = 0; /// Erase single page. Page size depends on target /// @param page_offset must be aligned to a page boundary. /// @return false if erase was aborted (e.g. 'cause page is locked) virtual bool erase_page(uint_t page_offset); /// Write data into flash. Empty data block are skipped. /// Modified parts of flash should be bllank. virtual void flash_write(const DataSectionStore §ions) = 0; /// Compare specified data to data from flash. Empty blocks are skipped. /// @return false if verification failed virtual bool flash_verify_by_crc(const DataSectionStore §ions); /// Compare specified data to data from flash. Empty blocks are skipped. /// @return false if verification failed virtual bool flash_verify_by_read(const DataSectionStore §ions); /// prepare reading procedure void flash_read_start(); /// finish reading procedure void flash_read_end(); /// read flash block (offset and size are not limited by any boundares\banks) /// @param offset absolute flash offset virtual void flash_read_block(size_t offset, size_t size, ByteVector &data) = 0; void read_debug_status(uint8_t &status); void read_debug_config(uint8_t &config); void write_debug_config(uint8_t config); void read_sfr(uint8_t address, uint8_t &value); void write_sfr(uint8_t address, uint8_t value); void write_xdata_memory(uint16_t address, const ByteVector &data); void write_xdata_memory(uint16_t address, const uint8_t data[], size_t size); void write_xdata_memory(uint16_t address, uint8_t data); void read_xdata_memory(uint16_t address, size_t count, ByteVector &out); uint8_t read_xdata_memory(uint16_t address); /// @param debug_mode if true after reset target will be halted void reset(bool debug_mode); uint_t lock_data_size() const; bool set_flash_size(uint_t flash_size); void set_programmer_ID(const USB_DeviceID& programmer_ID); CC_UnitDriver(USB_Device &programmer, ProgressWatcher &pw); protected: void select_info_page_flash(bool select_info_page); /// Read data from the 16-bit address space. Bank number is not changed. /// Result data will be appended to the end of data void flash_read_near(uint16_t address, size_t size, ByteVector &data); /// Read any block size void flash_read(size_t offset, size_t size, ByteVector &data);//todo: rename!!! void set_reg_info(const UnitCoreInfo &); UnitCoreInfo get_reg_info(); void write_flash_slow(const DataSectionStore §ions); //void write_flash_word(const DataSectionStore §ions); void write_lock_to_info_page(uint8_t lock_byte); //void /// @return true if specified memory block contains only 1s () bool empty_block(const uint8_t* data, size_t size); /// Convert list of string qulifiers 'debug', 'flash:xx', 'boot' void convert_lock_data_std_set( const StringVector& qualifiers, const ByteVector& lock_sizes, ByteVector& lock_data); USB_Device &usb_device_; ProgressWatcher &pw_; UnitInfo unit_info_; uint8_t endpoint_in_; uint8_t endpoint_out_; private: uint16_t calc_block_crc(); UnitCoreInfo reg_info_; }; typedef boost::shared_ptr CC_UnitDriverPtr; typedef std::list CC_UnitDriverPtrList; #endif // !_CC_UNIT_DRIVER_H_ cc-tool-0.27/src/programmer/cc_unit_info.cpp000066400000000000000000000021301371037307000211040ustar00rootroot00000000000000/* * cc_uint_info.cpp * * Created on: Nov 7, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "cc_unit_info.h" //============================================================================== UnitInfo::UnitInfo() : ID(0), internal_ID(0), revision(0), flags(0), flash_size(0), max_flash_size(0), ram_size(0), mac_address_count(0), mac_address_size(0), flash_page_size(0) { } //============================================================================== UnitCoreInfo::UnitCoreInfo() { memset(this, 0, sizeof(UnitCoreInfo)); } //============================================================================== size_t UnitInfo::actual_flash_size() const { return 1024 * (flash_size ? flash_size : max_flash_size); } #define CHECK_PARAM(x) check_param(x, __FILE__, __LINE__) //============================================================================== void check_param(bool assert, const String& module, uint_t line) { if (assert) return; throw std::runtime_error("internal error at " + module + ":" + number_to_string(line)); } cc-tool-0.27/src/programmer/cc_unit_info.h000066400000000000000000000033211371037307000205540ustar00rootroot00000000000000/* * cc_uint_info.h * * Created on: Aug 2, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _CC_UNIT_INFO_H_ #define _CC_UNIT_INFO_H_ #include "common.h" #include "data/data_section.h" struct Unit_ID { uint_t ID; String name; Unit_ID() : ID(0) { } Unit_ID(uint_t ID_, const String &name_) : ID(ID_), name(name_) { } }; struct UnitInfo { enum Flags { SUPPORT_USB = 0x01, // remove SUPPORT_MAC_ADDRESS = 0x02, // remove, use mac_address_count to checck SUPPORT_INFO_PAGE = 0x04 }; uint_t ID; // ID used by programmer String name; // like 'CCxxxx' uint8_t internal_ID; // read from chip uint8_t revision; // read from chip uint_t flags; uint_t flash_size; // in KB uint_t max_flash_size; // in KB UintVector flash_sizes; // list of possible flash sizes, in KB uint_t ram_size; // in KB uint_t mac_address_count; uint_t mac_address_size; uint_t flash_page_size; // in KB size_t actual_flash_size() const; UnitInfo(); }; struct UnitCoreInfo { size_t lock_size; // size_t flash_word_size; size_t verify_block_size; size_t write_block_size; uint16_t xbank_offset; uint16_t dma0_cfg_offset; uint16_t dma_data_offset; // Xdata register addresses; uint16_t memctr; uint16_t fmap; uint16_t rndl; uint16_t rndh; uint16_t fctl; uint16_t fwdata; uint16_t faddrl; uint16_t faddrh; uint16_t dma0_cfgl; uint16_t dma0_cfgh; uint16_t dma_arm; uint16_t dma_req; uint16_t dma_irq; uint8_t fctl_write; uint8_t fctl_erase; UnitCoreInfo(); }; typedef std::list Unit_ID_List; void check_param(bool assert, const String& module, uint_t line); #define CHECK_PARAM(x) check_param(x, __FILE__, __LINE__) #endif // !_CC_UNIT_INFO_H_ cc-tool-0.27/src/usb/000077500000000000000000000000001371037307000143635ustar00rootroot00000000000000cc-tool-0.27/src/usb/usb_device.cpp000066400000000000000000000263471371037307000172130ustar00rootroot00000000000000/* * usb_device.cpp * * Created on: Aug 2, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #include "usb_device.h" #include "log.h" static void on_error(const String &context, int error = LIBUSB_ERROR_OTHER); typedef std::vector libusb_device_vector; //============================================================================== class USB_Enumerator { public: USB_Enumerator(USB_ContextPtr context, libusb_device_vector &devices); ~USB_Enumerator(); private: libusb_device **list_; }; //============================================================================== USB_Enumerator::USB_Enumerator(USB_ContextPtr context, libusb_device_vector &devices) { ssize_t count = libusb_get_device_list(context.get(), &list_); if (count < 0) on_error("libusb_get_device_list", count); for (ssize_t i = 0; i < count; i++) devices.push_back(list_[i]); } //============================================================================== USB_Enumerator::~USB_Enumerator() { libusb_free_device_list(list_, true); } //============================================================================== static const char* libusb_error_string(enum libusb_error errcode) { switch (errcode) { case LIBUSB_SUCCESS: return "Success"; case LIBUSB_ERROR_IO: return "Input/output error"; case LIBUSB_ERROR_INVALID_PARAM: return "Invalid parameter"; case LIBUSB_ERROR_ACCESS: return "Access denied (insufficient permissions)"; case LIBUSB_ERROR_NO_DEVICE: return "No such device (it may have been disconnected)"; case LIBUSB_ERROR_NOT_FOUND: return "Entity not found"; case LIBUSB_ERROR_BUSY: return "Resource busy"; case LIBUSB_ERROR_TIMEOUT: return "Operation timed out"; case LIBUSB_ERROR_OVERFLOW: return "Overflow"; case LIBUSB_ERROR_PIPE: return "Pipe error"; case LIBUSB_ERROR_INTERRUPTED: return "System call interrupted (perhaps due to signal)"; case LIBUSB_ERROR_NO_MEM: return "Insufficient memory"; case LIBUSB_ERROR_NOT_SUPPORTED: return "Operation not supported or unimplemented on this platform"; case LIBUSB_ERROR_OTHER: return "Other error"; default: return "Unknown error"; } } //============================================================================== static void on_error(const String &context, int error) { throw std::runtime_error(context + " failed, " + libusb_error_string((libusb_error)error)); } //============================================================================== static void on_timeout_error(const String &context, ssize_t total, ssize_t transferred) { std::stringstream ss; ss << context << " timeout, transferred " << transferred << " from " << total; throw std::runtime_error(ss.str()); } //============================================================================== USB_Device::USB_Device() : handle_(NULL), device_(NULL), timeout_(0) { } //============================================================================== USB_Device::~USB_Device() { close(); } //============================================================================== void USB_Device::init_context() { if (context_) return; libusb_context *context = NULL; int result = libusb_init(&context); if (result != LIBUSB_SUCCESS) on_error("Failed to init USB context", result); context_ = USB_ContextPtr(context, libusb_exit); } //============================================================================== bool USB_Device::opened() const { return handle_ != NULL; } //============================================================================== void USB_Device::close() { if (handle_) { libusb_close(handle_); handle_ = NULL; } } //============================================================================== bool USB_Device::open_by_vid_pid(uint16_t vendor_id, uint16_t product_id) { init_context(); close(); libusb_device_vector devices; USB_Enumerator enumerator(context_, devices); libusb_device_descriptor descriptor; foreach (libusb_device *item, devices) { if (!libusb_get_device_descriptor(item, &descriptor) && descriptor.idVendor == vendor_id && descriptor.idProduct == product_id) { int result = libusb_open(item, &handle_); if (result < 0) on_error("libusb_open", result); device_ = libusb_get_device(handle_); log_info("usb, open device, VID: %04Xh, PID: %04Xh", vendor_id, product_id); return true; } } return false; } //============================================================================== bool USB_Device::open_by_address(uint8_t bus_number, uint8_t device_address) { init_context(); close(); libusb_device_vector devices; USB_Enumerator enumerator(context_, devices); foreach (libusb_device *item, devices) { if (libusb_get_bus_number(item) == bus_number && libusb_get_device_address(item) == device_address) { int result = libusb_open(item, &handle_); if (result < 0) on_error("libusb_open", result); device_ = libusb_get_device(handle_); return true; } } return false; } //============================================================================== void USB_Device::check_open() { if (!opened()) on_error("try using not-opened device"); } //============================================================================== void USB_Device::device_decriptor(libusb_device_descriptor &descriptor) { check_open(); int result = libusb_get_device_descriptor(device_, &descriptor); if (result != LIBUSB_SUCCESS) on_error("Failed to get device descriptor", (libusb_error)result); } //============================================================================== void USB_Device::string_descriptor_utf8(uint8_t index, uint16_t language, String &data) { check_open(); uint8_t raw_data[256]; int result = libusb_get_string_descriptor(handle_, index, language, raw_data, sizeof(raw_data)); if (result < 0) on_error("Failed to get string descriptor " + number_to_string(index), (libusb_error)result); data.assign(raw_data, raw_data + result); raw_data[result] = '\0'; log_info("usb, get string descriptor %u, language: %u, data: %s", index, language, raw_data); } //============================================================================== void USB_Device::string_descriptor_ascii(uint8_t index, String &data) { check_open(); uint8_t raw_data[256]; int result = libusb_get_string_descriptor_ascii(handle_, index, raw_data, sizeof(raw_data)); if (result < 0) on_error("Failed to get string descriptor " + number_to_string(index), (libusb_error)result); data.assign(raw_data, raw_data + result); raw_data[result] = '\0'; log_info("usb, get string descriptor %u, data: %s", index, raw_data); } //============================================================================== void USB_Device::set_transfer_timeout(uint_t timeout) { log_info("usb, set timeout %u ms", timeout); timeout_ = timeout; } //============================================================================== void USB_Device::set_debug_mode(DebugLevel level) { #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000106) libusb_set_option(context_.get(), LIBUSB_OPTION_LOG_LEVEL, level); #else libusb_set_debug(context_.get(), level); #endif } //============================================================================== void USB_Device::reset_device() { libusb_reset_device(handle_); } //============================================================================== void USB_Device::claim_interface(uint_t interface_number) { log_info("usb, claim interface %u", interface_number); int result = libusb_claim_interface(handle_, interface_number); if (result < 0) on_error("claim_interface", result); } //============================================================================== void USB_Device::release_interface(uint_t interface_number) { log_info("usb, release interface %u", interface_number); int result = libusb_release_interface(handle_, interface_number); if (result < 0) on_error("release_interface", result); } //============================================================================== void USB_Device::set_configuration(uint_t configuration) { log_info("usb, set configuration %u", configuration); int result = libusb_set_configuration(handle_, configuration); if (result < 0) on_error("set_configuration", result); } //============================================================================== void USB_Device::bulk_read(uint8_t endpoint, size_t count, uint8_t data[]) { int transferred = 0; endpoint |= LIBUSB_ENDPOINT_IN; ssize_t result = libusb_bulk_transfer(handle_, endpoint, data, count, &transferred, timeout_); log_info("usb, bulk read, count %u: data: %s", count, binary_to_hex(data, transferred, " ").c_str()); if (result < 0) on_error("libusb_bulk_transfer (in)", result); if ((int)count != transferred) on_timeout_error("libusb_bulk_transfer (in)", count, transferred); } //============================================================================== void USB_Device::bulk_write(uint8_t endpoint, size_t count, const uint8_t data[]) { log_info("usb, bulk write, count: %u, data: %s", count, binary_to_hex(data, count, " ").c_str()); int transferred = 0; endpoint |= LIBUSB_ENDPOINT_OUT; ssize_t result = libusb_bulk_transfer(handle_, endpoint, const_cast(data), count, &transferred, timeout_); if (result < 0) on_error("libusb_bulk_transfer (out)", result); if ((int)count != transferred) on_timeout_error("libusb_bulk_transfer (out)", count, transferred); } //============================================================================== void USB_Device::control_write(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, const uint8_t data[], size_t count) { bmRequestType |= LIBUSB_ENDPOINT_OUT; log_info("usb, control write, request_type: %02Xh, request: %02Xh, value: %04Xh, index: %04Xh, count: %u", bmRequestType, bRequest, wValue, wIndex, count); if (count) log_info("usb, control write, data: %s", binary_to_hex(data, count, " ").c_str()); ssize_t result = libusb_control_transfer(handle_, bmRequestType, bRequest, wValue, wIndex, const_cast(data), count, timeout_); if (result < 0) on_error("libusb_control_transfer (out)", result); if (count && (ssize_t)count != result) on_timeout_error("libusb_control_transfer (out)", count, result); } //============================================================================== void USB_Device::control_read(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t data[], size_t count) { bmRequestType |= LIBUSB_ENDPOINT_IN; log_info("usb, control read, request_type: %02Xh, request: %02Xh, value: %04Xh, index: %04Xh, count: %u", bmRequestType, bRequest, wValue, wIndex, count); ssize_t result = libusb_control_transfer(handle_, bmRequestType, bRequest, wValue, wIndex, data, count, timeout_); if (result < 0) on_error("libusb_control_transfer (in)", result); if (count && (ssize_t)count != result) on_timeout_error("libusb_control_transfer (in)", count, result); log_info("usb, control read, data: %s", binary_to_hex(data, count, " ").c_str()); } cc-tool-0.27/src/usb/usb_device.h000066400000000000000000000034461371037307000166530ustar00rootroot00000000000000/* * usb_device.h * * Created on: Aug 2, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _USB_DEVICE_H_ #define _USB_DEVICE_H_ #include #include #include "common.h" typedef boost::shared_ptr USB_ContextPtr; class USB_Device : boost::noncopyable { public: enum DebugLevel { DL_OFF = 0, DL_ERROR, DL_WARNING, DL_INFORMATION }; void set_debug_mode(DebugLevel level); void set_transfer_timeout(uint_t timeout); void reset_device(); void set_configuration(uint_t configuration); // throw void claim_interface(uint_t interface_number); // throw void release_interface(uint_t interface_number); // throw void device_decriptor(libusb_device_descriptor &descriptor); // throw void string_descriptor_utf8(uint8_t index, uint16_t language, String &data); // throw void string_descriptor_ascii(uint8_t index, String &data); // throw void clear_halt(uint8_t endpoint); void bulk_read(uint8_t endpoint, size_t count, uint8_t data[]); // throw void bulk_write(uint8_t endpoint, size_t count, const uint8_t data[]); // throw void control_write(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, const uint8_t data[], size_t count); // throw void control_read(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t data[], size_t count); // throw bool open_by_vid_pid(uint16_t vendor_id, uint16_t product_id); // throw bool open_by_address(uint8_t bus_number, uint8_t device_address); // throw bool opened() const; void close(); USB_Device(); ~USB_Device(); private: void init_context(); void check_open(); USB_ContextPtr context_; libusb_device_handle *handle_; libusb_device *device_; uint_t timeout_; }; #endif // !_USB_DEVICE_H_ cc-tool-0.27/src/version.h000066400000000000000000000006451371037307000154350ustar00rootroot00000000000000/* * version.h * * Created on: Jul 28, 2011 * Author: George Stark * * License: GNU GPL v2 * */ #ifndef _VERSION_H_ #define _VERSION_H_ #include "common.h" const uint_t VERSION_MAJOR = 0; const uint_t VERSION_MINOR = 26; const char MODULE_NAME[] = "cc-tool"; const char MODULE_DESCRIPTION[] = "Texas Instruments 8051-based System-On-Chip device programmer"; #endif // !_VERSION_H_ cc-tool-0.27/udev/000077500000000000000000000000001371037307000137465ustar00rootroot00000000000000cc-tool-0.27/udev/90-cc-debugger.rules000066400000000000000000000007131371037307000174200ustar00rootroot00000000000000# SmartRF05 Evaluation Board ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a0", MODE="0666" # SmartRF04 Evaluation Board ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="11a0", ATTRS{idProduct}=="db20", MODE="0666" ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="11a0", ATTRS{idProduct}=="eb20", MODE="0666" # CC Debugger ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a2", MODE="0666"