lpc21isp.c 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192
  1. /******************************************************************************
  2. Project: Portable command line ISP for NXP LPC1000 / LPC2000 family
  3. and Analog Devices ADUC70xx
  4. Filename: lpc21isp.c
  5. Compiler: Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,
  6. GCC Cygwin, GCC Linux, GCC ARM ELF
  7. Author: Martin Maurer (Martin.Maurer@clibb.de)
  8. Copyright: (c) Martin Maurer 2003-2011, All rights reserved
  9. Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com
  10. This file is part of lpc21isp.
  11. lpc21isp is free software: you can redistribute it and/or modify
  12. it under the terms of the GNU Lesser General Public License as published by
  13. the Free Software Foundation, either version 3 of the License, or
  14. any later version.
  15. lpc21isp is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU Lesser General Public License for more details.
  19. You should have received a copy of the GNU Lesser General Public License
  20. and GNU General Public License along with lpc21isp.
  21. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #if defined(_WIN32)
  24. #if !defined __BORLANDC__
  25. #include "StdAfx.h" // Precompiled Header for WIN32
  26. #endif
  27. #endif // defined(_WIN32)
  28. #include "lpc21isp.h" // if using propriatory serial port communication (customize attached lpc21isp.h)
  29. #include "adprog.h"
  30. #include "lpcprog.h"
  31. #include "lpcterm.h"
  32. /*
  33. Change-History:
  34. 1.00 2004-01-08 Initial Version, tested for MSVC6/7 and GCC under Cygwin
  35. 1.01 2004-01-10 Porting to Linux (at least compiling must work)
  36. 1.02 2004-01-10 Implemented conversion intel hex format -> binary
  37. 1.03 2004-01-25 Preparation to upload to public website
  38. 1.04 2004-02-12 Merged in bugfixes by Soeren Gust
  39. 1.05 2004-03-14 Implement printing of error codes as text / strings
  40. 1.06 2004-03-09 Merged in bugfixes by Charles Manning:
  41. The '?' sychronisation does not reliably respond to the first '?'.
  42. I added some retries.
  43. The LPC2106 sometimes responds to the '?' by echoing them back.
  44. This sometimes causes an attempt to match "?Synchonized".
  45. Added code to strip off any leading '?'s.
  46. Timeouts were too long.
  47. Change from RTS/CTS to no flow control.
  48. Done because many/most people will use only 3-wire comms.
  49. Added some progress tracing.
  50. 1.07 2004-03-14 Implement handling of control lines for easier booting
  51. 1.08 2004-04-01 Bugfix for upload problem
  52. 1.09 2004-04-03 Redesign of upload routine
  53. Now always 180 byte blocks are uploaded, to prevent
  54. small junks in uuencoding
  55. 1.10 2004-04-03 Clear buffers before sending commands to LPC21xx,
  56. this prevents synchronizing errors when previously loaded
  57. program does a lot of output, so FIFO of PC runs full
  58. 1.11 2004-04-03 Small optimization for controlling reset line
  59. otherwise termonly starts LPC twice, free PC buffers
  60. 1.12 2004-04-04 Add switch to enable logging terminal output to lpc21isp.log
  61. 1.13 2004-05-19 Merged in improvement by Charles Manning:
  62. Instead of exiting the wrong hex file size is corrected
  63. 1.14 2004-07-07 Merged in improvement by Alex Holden:
  64. Remove little/big endian dependancy
  65. 1.15 2004-09-27 Temporary improvement by Cyril Holweck:
  66. Removed test (data echoed = data transmited) on the main
  67. data transfert, since this was the biggest failure
  68. reason and is covered by checksome anyway.
  69. Added COMPILE_FOR_LPC21, to have target dump it's own
  70. memory to stdout.
  71. 1.16 2004-10-09 Merged in bugfix / improvement by Sinelnikov Evgeny
  72. I found out that Linux and Windows serial port initialization
  73. are different with pinouts states. My board don't get
  74. reset signal at first cycle of DTR pinout moving.
  75. And I add this moving to initalization cycle.
  76. 1.17 2004-10-21 Changes by Cyril Holweck
  77. Divide main, take out the real programming function, that can
  78. also be used by a target to copy its own code to another.
  79. 1.18 2004-10-26 Changes by Cyril Holweck
  80. Added a "G 0 A\r\n" at end of programming to run code.
  81. 1.19 2004-11-03 Changes by Robert Adsett
  82. Add support for Analog Devices.
  83. Separate file load from programming.
  84. Change from a debug on/off flag to debug level
  85. Remove if (debug) tests and replace with DebugPrintf
  86. statements.
  87. Change serial I/O and timing so that the system
  88. dependancies are isolated to a few portability functions.
  89. Add support for binary serial I/O.
  90. Add doxygen support.
  91. 1.20 2004-11-07 Preparation for multiport booting (factory support)
  92. 1.21 2004-11-08 Bugfix from Robert Adsett
  93. BinaryLength was not initialized
  94. 1.22 2004-11-08 Changes from Cyril Holweck / Evgeny Sinelnikov
  95. Forgotten IspEnvironment-> and bugfixes if COMPILE_FOR_LINUX
  96. If COMPILE_FOR_LPC21, PhilipsDownload() 'acts as' main():
  97. - it should not be static and should return int.
  98. - no sub-function can use exit() but only return ()
  99. Use 'char' instead of 'byte' ;)
  100. 1.23 2005-01-16 Build in automatic detection of LPC chiptype
  101. (needed for 256 KByte support)
  102. 1.24B 2005-06-02 Changes by Thiadmer Riemersma: completed support for other
  103. chip types (LPC213x series and others).
  104. 1.24C 2005-06-11 Changes by Thiadmer Riemersma: added the device ID codes for
  105. chip types LPC2131 and LPC2132.
  106. 1.25 2005-06-19 Martin Maurer: Setup more parameters in DCB,
  107. otherwise wrong code is downloaded (only Windows and Cygwin)
  108. when a previous program has changed these parameters
  109. Check exact string of "G 0 A\r\n0\r\n" instead of whole received buffer,
  110. to prevent checking of already received by program start
  111. (error on running program, but reports CMD_SUCCESS)
  112. Add ifdefs for all baudrates (needed only for high baudrate,
  113. which seem to be not available on Macs...)
  114. 1.26 2005-06-26 Martin Maurer:
  115. Correct check again: "G 0 A\r\n0\r\n" is cutted, because of reboot
  116. (error on running program, but reports CMD_SUCCESS)
  117. 1.27 2005-06-29 Martin Maurer:
  118. Add LPC chip ID's (thanks to Robert from Philips) for
  119. missing LPC213x and upcoming new LPC214x chips
  120. (currently untested, because i don't have access to these chips,
  121. please give me feedback !)
  122. 1.28 2005-07-27 Anders Rosvall / Embedded Artists AB:
  123. Changed the reset timeout to 500 ms when entering the bootloader.
  124. Some external reset controllers have quite long timeout periods,
  125. so extening the timeout delay would be a good thing.
  126. 1.29 2005-09-14 Rob Jansen:
  127. Added functionality to download to RAM and run from there.
  128. In LoadFile() added record types 04 (Extended Linear Address Record)
  129. and 05 (Start Linear Address Record), added address offset
  130. (IspEnvironment->BinaryOffset) and start address (...->StartAddress).
  131. Changed PhilipsDownload to skip all Flash prepare/erase/copy commands.
  132. Note: Tested with VC7 only
  133. 1.30 2005-10-04 Rob Jansen:
  134. - forgot to change the version string in 1.29
  135. - Wrong text in LoadFile corrected (printed text mentions record type 05,
  136. this should be 04
  137. - Changed LoadFile to accept multiple record types 04
  138. - Changed LoadFile to check on memory size, will not load more than x MB
  139. if linear extended address records are used
  140. 1.31 2005-11-13 Martin Maurer: Thanks to Frank Gutmann
  141. Updated number of sectors in device table
  142. for LPC2194, LPC2292 and LPC2294
  143. 1.32 2005-12-02 Martin Maurer: Corrected missing control of RTS/DTR
  144. in case user selected -termonly and -control
  145. Small correction (typo in debug)
  146. 1.33 2006-10-01 Jean-Marc Koller:
  147. Added support for MacOS X (difference on how to set termios baudrate).
  148. 1.34 2006-10-01 Cyril Holweck:
  149. Made it compile again for lpc21isp
  150. Added const keyword to constant variables to make it better
  151. code for embeded target. (decrease RAM usage)
  152. Replaced all regular call to printf() by DebugPrintf()
  153. Removed call to scanf() (not much usefull and cost a lot to my target)
  154. 1.35 2006-22-01 Cyril Holweck
  155. Added feature for LPC21: will start downloading at Sector 1 and upward,
  156. to finish with Sector 0, the one containing the checksum controling BSL entry
  157. 1.36 2006-25-01 Cyril Holweck
  158. PhilipsDownload() will now return a unique error code for each error
  159. 1.37 2006-10-03 Jeroen Domburg
  160. Added LPC2103 (and only the 2103, I can't find the IDs for 2101/2102)
  161. Corrected a loop which occured if the program completely fits in sector 0
  162. 1.38 2007-01-05 Ray Molenkamp
  163. Added feature for LPC21: Wipe entire device before programming to enable
  164. reflashing of chips with the lpc codeprotection feature enabled.
  165. 1.39 2007-01-12 Martin Maurer
  166. Added initial support for new processors LPC23xx and LPC24xx
  167. 1.40 2007-01-22 Martin Maurer
  168. Correction of chip id of LPC2458
  169. 1.41 2007-01-28 Jean-Marc Koller
  170. Modified Terminal() to disable ECHO with termios only once, instead of
  171. modifying and restoring termios in each getch and kbhit call (which caused
  172. a strange echo behaviour in MacOS X).
  173. 1.42 2007-01-28 Rob Probin
  174. Added -localecho command to allow local echoing in terminal mode for use
  175. where target does not echo back keystrokes.
  176. 1.43 2007-01-29 Martin Maurer
  177. Moved keyboard handling routines to own subroutines,
  178. so they can be used during aborting synchronisation.
  179. Newest cygwin made problems, StringOscillator always contained '\0x0d'
  180. at the end, when calling lpc21isp from batch file
  181. 1.44 2007-02-23 Yang Yang
  182. Added feature for LPC21: Verify the data in Flash after every writes
  183. to sector. To detect errors in writing to Flash ROM.
  184. 1.45 2007-02-25 Martin Maurer
  185. Replace printf syntax of DumpString by a simple pointer to a string
  186. printf syntax is a nice thing, but it is not working :-(
  187. and therefore makes debugging much more difficult...
  188. Moved VERSION_STR to top of file to avoid possible cosmetical errors
  189. 1.46 2007-02-25 Martin Maurer
  190. Again corrected debug output: should solve output of
  191. (FFFFFFB5) instead of (B5)
  192. 1.47 2007-02-27 Robert Adsett
  193. Raised timeout on AD send packet function.
  194. 1.48 2007-04-20 Martin Maurer
  195. Thanks to Josef Wolf for preventing to overwrite over end of array
  196. 1.49 2007-10-16 New Option -halfduplex allow single wire using.
  197. Implemented and tested only for Windows. Data Resend implemented.
  198. 1.50 2007-10-31 Changes by Simon Ellwood
  199. Formated the code for readablity
  200. Fixed some c++ compiler issues
  201. 1.51 2007-11-20 Changes by Simon Ellwood
  202. Split into seperate files
  203. Made more modular so when used in an embedded mode only the required code is built
  204. 1.52 2008-01-22 Changes by Manuel Koeppen
  205. Made compileable again for linux and windows
  206. Fixed bug in ClearSerialPortBuffers (linux)
  207. 1.53 2008-02-25 Changes by Michael Roth
  208. Get priority of debug messages wih -control right
  209. 1.54 2008-03-03 Martin Maurer
  210. Try to bring lpc21isp back to a useable state in Windows, Cygwin, Linux and Mac OS.
  211. Merged in changes by Erika Stefanini, which were done only for old version 1.49:
  212. Added device ids for revision B chips
  213. 1.55 2008-03-03 Martin Maurer
  214. Thanks to Fausto Marzoli, bugfix for compiling latest version under Linux
  215. 1.56 2008-04-01 Steve Franks
  216. Integrate FreeBSD patch.
  217. Add support for swapping and/or inverting RTS & DTR
  218. 1.57 2008-04-06 Mauricio Scaff
  219. Changed OpenSerialPort to work with MacOS
  220. Corrected the number of sectors in some 512K devices (28 instead of 27)
  221. Added support for LPC2387 and LPC2388
  222. Defined BL error 19 (Code Protected)
  223. 1.58 2008-05-10 Herbert Demmel dh2@demmel.com
  224. I had the special requirement to integrate the program into my own Windows
  225. software compiled with Borland C++ Builder 5. I had to do some minor changes
  226. for Borland (see defined __BORLANDC__) and modified to code slightly to have
  227. some simple callbacks for screen i/o (see define INTEGRATED_IN_WIN_APP).
  228. Please notet that I don *not* check / modify the part for AnalogDevices !!
  229. Besides that I fixed some minor issues:
  230. added dcb.fOutxCtsFlow = FALSE and dcb.fOutxDsrFlow = FALSE (sometimes required)
  231. Now comparing one character less of answer to "Now launching ... code" command
  232. 1.59 2008-07-07 Peter Hayward
  233. Fixed freeze under Windows XP SP2 by removing redundant call to SetCommMask.
  234. 1.60 2008-07-21 Martin Maurer
  235. Added uptodate part ids for LPC2458, LPC2468 and LPC2478
  236. Add comment "obsolete" for older part ids for LPC2458 and LPC2468
  237. Add ", " between compile date and time
  238. 1.61 2008-10-21 Fausto Marzoli (thanks to Geoffrey Wossum for the patches)
  239. Fix for compiling latest version under Linux and "ControlLinesSwapped" issue
  240. 1.62 2008-11-19 Martin Maurer
  241. Added (untested) support for LPC2109
  242. Added (untested) support for LPC2361 / LPC2362
  243. Heavy update of part identification number of LPC23xx and LPC24xx
  244. Correct bug, that hex file must exist, when "-detectonly" is used
  245. Correct Makefile.vc: use /Fe instead of -o
  246. 1.63 2008-11-23 Martin Maurer
  247. Changed to GNU Lesser General Public License
  248. 1.64 2009-01-19 Steve Franks
  249. __FREEBSD__ changed to __FreeBSD__ at some point, plus other com port fixes
  250. 1.65 2009-03-26 Vito Marolda
  251. Added pre-erasure of sector 0 to invalidate checksum before starting
  252. modification of the other sectors, so that the bootloader restarts
  253. if programming gets aborted while writing on a non-empty part.
  254. 1.66 2009-03-26 Vito Marolda
  255. Corrected interpretation of intel hex record 03 which is execution start address
  256. and not data segment address
  257. 1.67 2009-04-19 SASANO Takayoshi
  258. Add OpenBSD support
  259. 1.68 2009-05-17 Martin Maurer
  260. Merge in changes done by Bruno Quoitin (baudrate problem when __APPLE__ is used)
  261. Remove TABs from source code and replaced them with spaces
  262. 1.69 2009-06-18 Martin Maurer
  263. Add support for LPC17xx devices
  264. 1.70 2009-06-29 Martin Maurer
  265. Further improvement of LPC17xx support
  266. Workaround for booter (4.1) of LPC17xx, which does not echo all sent characters (0D,0A,...)
  267. ISP command GO seems to be broken:
  268. Sending 'G 196 T(0A)'
  269. Answer(Length=15): 'G 196 T(0A)0(0D)(0A)'
  270. leads to 'prefetch_abort_exception(0D)(0A)1FFF07A5'
  271. No solution known...need your help here...
  272. Manual workaround: Use DTR and RTS toggling to start application (e.g. 2 batch files)
  273. 1.71 2009-07-19 Martin Maurer
  274. Added LPC17xx with CPUID starting with 0x26 (not according user manual)
  275. 1.72 2009-09-14 Martin Maurer
  276. Add support for LPC13xx devices
  277. 1.73 2009-09-14 Martin Maurer
  278. Correct again (hopefully the last time) the CPUIDs for some LPC17xx devices
  279. (Now according to User Manual LPC17xx Version 00.07 (31 July 2009))
  280. 1.74 2009-09-14 Mario Ivancic
  281. Added support for multiple HEX files, besed on internal version 1.37B.
  282. NOTE: this feature is used in production in 1.37B but is not tested in this version.
  283. Added numeric debug level command line switch -debugn, n=[0-5]
  284. Added command line scitch -try n to specify nQuestionMarks limit. Defaul: 100
  285. Merged in DoNotStart patch from cgommel_new
  286. Static functions declarations moved from lpc21isp.h to this file
  287. Modified LoadFile() to return error_code instead exit(1)
  288. Removed IspEnvironment.debug_level, all code uses global debug_level
  289. 1.75 2010-01-05 Martin Maurer
  290. Added support for LPC11xx devices (not tested at all)
  291. Changed Product in LPC_DEVICE_TYPE from number to string to distinguish new LPC11 devices
  292. Changed "unsigned" to "unsigned int" in LPC_DEVICE_TYPE
  293. 1.76 2010-02-01 Published test version without source code
  294. 1.77 2010-02-01 Martin Maurer
  295. Corrected chip id of LPC1342 and LPC1343
  296. Added a new chip type for LPC11xx and LPC13xx microcontrollers
  297. Use higher area of RAM with LPC11xx and LPC13xx, because lower RAM is occupied by ISP
  298. Add code to lpcprog.c to read unique id, but not yet activate.
  299. Adapt block sizes for copying for each model of LPC11xx and LPC13xx
  300. 1.78 2010-02-16 Martin Maurer
  301. Corrected chip id of LPC1751
  302. Added support for LPC1759, LPC1767 and LPC1769
  303. 1.79 2010-02-19 Andrew Pines
  304. Added __APPLE__ flag to CFLAGS in Makefile to detect and handle OS X
  305. Added -Wall to Makefile to report warnings more comprehensively
  306. Added #define in lpc21isp.h to substitute strnicmp with strncasecmp (needed for Unix)
  307. Fixed a few format specifiers in lpcprog.c to eliminate some warnings
  308. 1.80 2010-03-04 Philip Munts
  309. Added entries to LPCtypes[] in lpcprog.c for obsolete revisions of LPC2364/6/8/78.
  310. Added entry to LPCtypes[] in lpcprog.c for new LPC2387.
  311. 1.81 2011-03-30 Mario Ivancic
  312. As per message #517 from Thiadmer Riemersma, removed WaitForWatchDog and WatchDogSeconds
  313. in PhilipsDownload().
  314. 1.82 2011-06-25 Moses McKnight
  315. Corrected MaxCopySize for a number of the LPC11xx series
  316. Added support for several more LPC11xx and LPC11Cxx series
  317. 1.83 2011-08-02 Martin Maurer
  318. Thanks to Conurus for detecting and fixing a bug with patching checksum
  319. (patching was too early, chip id was not yet available)
  320. (Re-)Added code to start downloaded via "G 0 T", when using LPC1xxx
  321. (Starting code at position 0 seems to work, compare to comment of version 1.70)
  322. Changed some occurances of Philips to NXP
  323. Added -static to Makefile (thanks to Camilo)
  324. Added support for LPC1311/01 and LPC1313/01 (they have separate identifiers)
  325. Correct flash size of LPC1342 to 16 KByte (thanks to Decio)
  326. Abort programming when unknown NXP chip id is detected
  327. */
  328. // Please don't use TABs in the source code !!!
  329. // Don't forget to update the version string that is on the next line
  330. #define VERSION_STR "1.83"
  331. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  332. static char RxTmpBuf[256]; // save received data to this buffer for half-duplex
  333. char * pRxTmpBuf = RxTmpBuf;
  334. #endif
  335. #if !defined COMPILE_FOR_LPC21
  336. int debug_level = 2;
  337. #endif
  338. static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS);
  339. static unsigned char Ascii2Hex(unsigned char c);
  340. #ifdef COMPILE_FOR_WINDOWS
  341. static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds);
  342. static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment);
  343. #endif // COMPILE_FOR_WINDOWS
  344. static int AddFileHex(ISP_ENVIRONMENT *IspEnvironment, const char *arg);
  345. static int AddFileBinary(ISP_ENVIRONMENT *IspEnvironment, const char *arg);
  346. static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat);
  347. #define ERR_RECORD_TYPE_LOADFILE 55 /** File record type not yet implemented. */
  348. #define ERR_ALLOC_FILE_LIST 60
  349. #define ERR_FILE_OPEN_HEX 61 /**< Couldn't open hex file. */
  350. #define ERR_FILE_SIZE_HEX 62 /**< Unexpected hex file size. */
  351. #define ERR_FILE_ALLOC_HEX 63 /**< Couldn't allocate enough memory for hex file. */
  352. #define ERR_FILE_ALLOC_BIN 64 /**< Couldn't allocate enough memory for bin file. */
  353. #define ERR_FILE_RECST_HEX 65 /**< Can't find start of record indicator for Intel Hex file.*/
  354. #define ERR_FILE_OPEN_BIN 66 /**< Couldn't open binary file. */
  355. #define ERR_FILE_SIZE_BIN 67 /**< Unexpected binary file size. */
  356. #define ERR_FILE_WRITE_BIN 68 /**< Couldn't write debug binary file to disk. How's that for ironic? */
  357. #define ERR_MEMORY_RANGE 69 /**< Out of memory range. */
  358. /************* Portability layer. Serial and console I/O differences */
  359. /* are taken care of here. */
  360. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  361. static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
  362. {
  363. DCB dcb;
  364. COMMTIMEOUTS commtimeouts;
  365. IspEnvironment->hCom = CreateFile(IspEnvironment->serial_port, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  366. if (IspEnvironment->hCom == INVALID_HANDLE_VALUE)
  367. {
  368. DebugPrintf(1, "Can't open COM-Port %s ! - Error: %ld\n", IspEnvironment->serial_port, GetLastError());
  369. exit(2);
  370. }
  371. DebugPrintf(3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
  372. GetCommState(IspEnvironment->hCom, &dcb);
  373. dcb.BaudRate = atol(IspEnvironment->baud_rate);
  374. dcb.ByteSize = 8;
  375. dcb.StopBits = ONESTOPBIT;
  376. dcb.Parity = NOPARITY;
  377. dcb.fDtrControl = DTR_CONTROL_DISABLE;
  378. dcb.fOutX = FALSE;
  379. dcb.fInX = FALSE;
  380. dcb.fNull = FALSE;
  381. dcb.fRtsControl = RTS_CONTROL_DISABLE;
  382. // added by Herbert Demmel - iF CTS line has the wrong state, we would never send anything!
  383. dcb.fOutxCtsFlow = FALSE;
  384. dcb.fOutxDsrFlow = FALSE;
  385. if (SetCommState(IspEnvironment->hCom, &dcb) == 0)
  386. {
  387. DebugPrintf(1, "Can't set baudrate %s ! - Error: %ld", IspEnvironment->baud_rate, GetLastError());
  388. exit(3);
  389. }
  390. /*
  391. * Peter Hayward 02 July 2008
  392. *
  393. * The following call is only needed if the WaitCommEvent
  394. * or possibly the GetCommMask functions are used. They are
  395. * *not* in this implimentation. However, under Windows XP SP2
  396. * on my laptop the use of this call causes XP to freeze (crash) while
  397. * this program is running, e.g. in section 5/6/7 ... of a largish
  398. * download. Removing this *unnecessary* call fixed the problem.
  399. * At the same time I've added a call to SetupComm to request
  400. * (not necessarity honoured) the operating system to provide
  401. * large I/O buffers for high speed I/O without handshaking.
  402. *
  403. * SetCommMask(IspEnvironment->hCom,EV_RXCHAR | EV_TXEMPTY);
  404. */
  405. SetupComm(IspEnvironment->hCom, 32000, 32000);
  406. SetCommMask(IspEnvironment->hCom, EV_RXCHAR | EV_TXEMPTY);
  407. commtimeouts.ReadIntervalTimeout = MAXDWORD;
  408. commtimeouts.ReadTotalTimeoutMultiplier = 0;
  409. commtimeouts.ReadTotalTimeoutConstant = 1;
  410. commtimeouts.WriteTotalTimeoutMultiplier = 0;
  411. commtimeouts.WriteTotalTimeoutConstant = 0;
  412. SetCommTimeouts(IspEnvironment->hCom, &commtimeouts);
  413. }
  414. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  415. #if defined COMPILE_FOR_LINUX
  416. static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
  417. {
  418. IspEnvironment->fdCom = open(IspEnvironment->serial_port, O_RDWR | O_NOCTTY | O_NONBLOCK);
  419. if (IspEnvironment->fdCom < 0)
  420. {
  421. int err = errno;
  422. DebugPrintf(1, "Can't open COM-Port %s ! (Error: %dd (0x%X))\n", IspEnvironment->serial_port, err, err);
  423. exit(2);
  424. }
  425. DebugPrintf(3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
  426. /* clear input & output buffers, then switch to "blocking mode" */
  427. tcflush(IspEnvironment->fdCom, TCOFLUSH);
  428. tcflush(IspEnvironment->fdCom, TCIFLUSH);
  429. fcntl(IspEnvironment->fdCom, F_SETFL, fcntl(IspEnvironment->fdCom, F_GETFL) & ~O_NONBLOCK);
  430. tcgetattr(IspEnvironment->fdCom, &IspEnvironment->oldtio); /* save current port settings */
  431. bzero(&IspEnvironment->newtio, sizeof(IspEnvironment->newtio));
  432. IspEnvironment->newtio.c_cflag = CS8 | CLOCAL | CREAD;
  433. #if defined(__FreeBSD__) || defined(__OpenBSD__)
  434. if(cfsetspeed(&IspEnvironment->newtio,(speed_t) strtol(IspEnvironment->baud_rate,NULL,10))) {
  435. DebugPrintf(1, "baudrate %s not supported\n", IspEnvironment->baud_rate);
  436. exit(3);
  437. };
  438. #else
  439. #ifdef __APPLE__
  440. #define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_ispeed = IspEnvironment->newtio.c_ospeed = bps;
  441. #else
  442. #define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_cflag |= bps;
  443. #endif
  444. switch (atol(IspEnvironment->baud_rate))
  445. {
  446. #ifdef B1152000
  447. case 1152000: NEWTERMIOS_SETBAUDARTE(B1152000); break;
  448. #endif // B1152000
  449. #ifdef B576000
  450. case 576000: NEWTERMIOS_SETBAUDARTE(B576000); break;
  451. #endif // B576000
  452. #ifdef B230400
  453. case 230400: NEWTERMIOS_SETBAUDARTE(B230400); break;
  454. #endif // B230400
  455. #ifdef B115200
  456. case 115200: NEWTERMIOS_SETBAUDARTE(B115200); break;
  457. #endif // B115200
  458. #ifdef B57600
  459. case 57600: NEWTERMIOS_SETBAUDARTE(B57600); break;
  460. #endif // B57600
  461. #ifdef B38400
  462. case 38400: NEWTERMIOS_SETBAUDARTE(B38400); break;
  463. #endif // B38400
  464. #ifdef B19200
  465. case 19200: NEWTERMIOS_SETBAUDARTE(B19200); break;
  466. #endif // B19200
  467. #ifdef B9600
  468. case 9600: NEWTERMIOS_SETBAUDARTE(B9600); break;
  469. #endif // B9600
  470. // Special value
  471. // case 32000: NEWTERMIOS_SETBAUDARTE(32000); break;
  472. default:
  473. {
  474. DebugPrintf(1, "unknown baudrate %s\n", IspEnvironment->baud_rate);
  475. exit(3);
  476. }
  477. }
  478. #endif
  479. IspEnvironment->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF;
  480. IspEnvironment->newtio.c_oflag = 0;
  481. /* set input mode (non-canonical, no echo,...) */
  482. IspEnvironment->newtio.c_lflag = 0;
  483. cfmakeraw(&IspEnvironment->newtio);
  484. IspEnvironment->newtio.c_cc[VTIME] = 1; /* inter-character timer used */
  485. IspEnvironment->newtio.c_cc[VMIN] = 0; /* blocking read until 0 chars received */
  486. tcflush(IspEnvironment->fdCom, TCIFLUSH);
  487. if(tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio))
  488. {
  489. DebugPrintf(1, "Could not change serial port behaviour (wrong baudrate?)\n");
  490. exit(3);
  491. }
  492. }
  493. #endif // defined COMPILE_FOR_LINUX
  494. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  495. static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
  496. {
  497. CloseHandle(IspEnvironment->hCom);
  498. }
  499. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  500. #if defined COMPILE_FOR_LINUX
  501. static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
  502. {
  503. tcflush(IspEnvironment->fdCom, TCOFLUSH);
  504. tcflush(IspEnvironment->fdCom, TCIFLUSH);
  505. tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->oldtio);
  506. close(IspEnvironment->fdCom);
  507. }
  508. #endif // defined COMPILE_FOR_LINUX
  509. /***************************** SendComPortBlock *************************/
  510. /** Sends a block of bytes out the opened com port.
  511. \param [in] s block to send.
  512. \param [in] n size of the block.
  513. */
  514. void SendComPortBlock(ISP_ENVIRONMENT *IspEnvironment, const void *s, size_t n)
  515. {
  516. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  517. unsigned long realsize;
  518. size_t m;
  519. unsigned long rxsize;
  520. char * pch;
  521. char * rxpch;
  522. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  523. DumpString(4, s, n, "Sending ");
  524. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  525. if (IspEnvironment->HalfDuplex == 0)
  526. {
  527. WriteFile(IspEnvironment->hCom, s, n, &realsize, NULL);
  528. }
  529. else
  530. {
  531. pch = (char *)s;
  532. rxpch = RxTmpBuf;
  533. pRxTmpBuf = RxTmpBuf;
  534. // avoid buffer otherflow
  535. if (n > sizeof (RxTmpBuf))
  536. n = sizeof (RxTmpBuf);
  537. for (m = 0; m < n; m++)
  538. {
  539. WriteFile(IspEnvironment->hCom, pch, 1, &realsize, NULL);
  540. if ((*pch != '?') || (n != 1))
  541. {
  542. do
  543. {
  544. ReadFile(IspEnvironment->hCom, rxpch, 1, &rxsize, NULL);
  545. }while (rxsize == 0);
  546. }
  547. pch++;
  548. rxpch++;
  549. }
  550. *rxpch = 0; // terminate echo string
  551. }
  552. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  553. #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
  554. write(IspEnvironment->fdCom, s, n);
  555. #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
  556. }
  557. /***************************** SendComPort ******************************/
  558. /** Sends a string out the opened com port.
  559. \param [in] s string to send.
  560. */
  561. void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s)
  562. {
  563. SendComPortBlock(IspEnvironment, s, strlen(s));
  564. }
  565. /***************************** SerialTimeoutTick ************************/
  566. /** Performs a timer tick. In this simple case all we do is count down
  567. with protection against underflow and wrapping at the low end.
  568. */
  569. static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment)
  570. {
  571. if (IspEnvironment->serial_timeout_count <= 1)
  572. {
  573. IspEnvironment->serial_timeout_count = 0;
  574. }
  575. else
  576. {
  577. IspEnvironment->serial_timeout_count--;
  578. }
  579. }
  580. /***************************** ReceiveComPortBlock **********************/
  581. /** Receives a buffer from the open com port. Returns all the characters
  582. ready (waits for up to 'n' milliseconds before accepting that no more
  583. characters are ready) or when the buffer is full. 'n' is system dependant,
  584. see SerialTimeout routines.
  585. \param [out] answer buffer to hold the bytes read from the serial port.
  586. \param [in] max_size the size of buffer pointed to by answer.
  587. \param [out] real_size pointer to a long that returns the amout of the
  588. buffer that is actually used.
  589. */
  590. static void ReceiveComPortBlock(ISP_ENVIRONMENT *IspEnvironment,
  591. void *answer, unsigned long max_size,
  592. unsigned long *real_size)
  593. {
  594. char tmp_string[32];
  595. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  596. if (IspEnvironment->HalfDuplex == 0)
  597. ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
  598. else
  599. {
  600. *real_size = strlen (pRxTmpBuf);
  601. if (*real_size)
  602. {
  603. if (max_size >= *real_size)
  604. {
  605. strncpy((char*) answer, pRxTmpBuf, *real_size);
  606. RxTmpBuf[0] = 0;
  607. pRxTmpBuf = RxTmpBuf;
  608. }
  609. else
  610. {
  611. strncpy((char*) answer, pRxTmpBuf, max_size);
  612. *real_size = max_size;
  613. pRxTmpBuf += max_size;
  614. }
  615. }
  616. else
  617. ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
  618. }
  619. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  620. #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
  621. *real_size = read(IspEnvironment->fdCom, answer, max_size);
  622. #endif // defined COMPILE_FOR_LINUX
  623. sprintf(tmp_string, "Read(Length=%ld): ", (*real_size));
  624. DumpString(5, answer, (*real_size), tmp_string);
  625. if (*real_size == 0)
  626. {
  627. SerialTimeoutTick(IspEnvironment);
  628. }
  629. }
  630. /***************************** SerialTimeoutSet *************************/
  631. /** Sets (or resets) the timeout to the timout period requested. Starts
  632. counting to this period. This timeout support is a little odd in that the
  633. timeout specifies the accumulated deadtime waiting to read not the total
  634. time waiting to read. They should be close enought to the same for this
  635. use. Used by the serial input routines, the actual counting takes place in
  636. ReceiveComPortBlock.
  637. \param [in] timeout_milliseconds the time in milliseconds to use for
  638. timeout. Note that just because it is set in milliseconds doesn't mean
  639. that the granularity is that fine. In many cases (particularly Linux) it
  640. will be coarser.
  641. */
  642. static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds)
  643. {
  644. #if defined COMPILE_FOR_LINUX
  645. IspEnvironment->serial_timeout_count = timeout_milliseconds / 100;
  646. #elif defined COMPILE_FOR_LPC21
  647. IspEnvironment->serial_timeout_count = timeout_milliseconds * 200;
  648. #else
  649. IspEnvironment->serial_timeout_count = timeout_milliseconds;
  650. #endif
  651. }
  652. /***************************** SerialTimeoutCheck ***********************/
  653. /** Check to see if the serial timeout timer has run down.
  654. \retval 1 if timer has run out.
  655. \retval 0 if timer still has time left.
  656. */
  657. static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment)
  658. {
  659. if (IspEnvironment->serial_timeout_count == 0)
  660. {
  661. return 1;
  662. }
  663. return 0;
  664. }
  665. #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
  666. /***************************** getch ************************************/
  667. /** Replacement for the common dos function of the same name. Reads a
  668. single unbuffered character from the 'keyboard'.
  669. \return The character read from the keyboard.
  670. */
  671. int getch(void)
  672. {
  673. char ch;
  674. /* Read in one character */
  675. read(0,&ch,1);
  676. return ch;
  677. }
  678. #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
  679. #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
  680. /***************************** kbhit ************************************/
  681. /** Replacement for the common dos function of the same name. Indicates if
  682. there are characters to be read from the console.
  683. \retval 0 No characters ready.
  684. \retval 1 Characters from the console ready to be read.
  685. */
  686. int kbhit(void)
  687. {
  688. /* return 0 for no key pressed, 1 for key pressed */
  689. int return_value = 0;
  690. /* time struct for the select() function, to only wait a little while */
  691. struct timeval select_time;
  692. /* file descriptor variable for the select() call */
  693. fd_set readset;
  694. /* we're only interested in STDIN */
  695. FD_ZERO(&readset);
  696. FD_SET(STDIN_FILENO, &readset);
  697. /* how long to block for - this must be > 0.0, but could be changed
  698. to some other setting. 10-18msec seems to work well and only
  699. minimally load the system (0% CPU loading) */
  700. select_time.tv_sec = 0;
  701. select_time.tv_usec = 10;
  702. /* is there a keystroke there? */
  703. if (select(1, &readset, NULL, NULL, &select_time))
  704. {
  705. /* yes, remember it */
  706. return_value = 1;
  707. }
  708. /* return with what we found out */
  709. return return_value;
  710. }
  711. struct termios keyboard_origtty;
  712. #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
  713. /***************************** PrepareKeyboardTtySettings ***************/
  714. /** Set the keyboard tty to be able to check for new characters via kbhit
  715. getting them via getch
  716. */
  717. void PrepareKeyboardTtySettings(void)
  718. {
  719. #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
  720. /* store the current tty settings */
  721. if (!tcgetattr(0, &keyboard_origtty))
  722. {
  723. struct termios tty;
  724. /* start with the current settings */
  725. tty = keyboard_origtty;
  726. /* make modifications to put it in raw mode, turn off echo */
  727. tty.c_lflag &= ~ICANON;
  728. tty.c_lflag &= ~ECHO;
  729. tty.c_lflag &= ~ISIG;
  730. tty.c_cc[VMIN] = 1;
  731. tty.c_cc[VTIME] = 0;
  732. /* put the settings into effect */
  733. tcsetattr(0, TCSADRAIN, &tty);
  734. }
  735. #endif
  736. }
  737. /***************************** ResetKeyboardTtySettings *****************/
  738. /** Reset the keyboard tty to original settings
  739. */
  740. void ResetKeyboardTtySettings(void)
  741. {
  742. #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
  743. /* reset the tty to its original settings */
  744. tcsetattr(0, TCSADRAIN, &keyboard_origtty);
  745. #endif
  746. }
  747. #if !defined COMPILE_FOR_LPC21
  748. /***************************** ControlModemLines ************************/
  749. /** Controls the modem lines to place the microcontroller into various
  750. states during the programming process.
  751. error rather abruptly terminates the program.
  752. \param [in] DTR the state to set the DTR line to.
  753. \param [in] RTS the state to set the RTS line to.
  754. */
  755. static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS)
  756. {
  757. //handle wether to invert the control lines:
  758. DTR ^= IspEnvironment->ControlLinesInverted;
  759. RTS ^= IspEnvironment->ControlLinesInverted;
  760. //handle wether to swap the control lines
  761. if (IspEnvironment->ControlLinesSwapped)
  762. {
  763. unsigned char tempRTS;
  764. tempRTS = RTS;
  765. RTS = DTR;
  766. DTR = tempRTS;
  767. }
  768. #if defined COMPILE_FOR_LINUX
  769. int status;
  770. if (ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
  771. {
  772. DebugPrintf(3, "ioctl get ok, status = %X\n",status);
  773. }
  774. else
  775. {
  776. DebugPrintf(1, "ioctl get failed\n");
  777. }
  778. if (DTR) status |= TIOCM_DTR;
  779. else status &= ~TIOCM_DTR;
  780. if (RTS) status |= TIOCM_RTS;
  781. else status &= ~TIOCM_RTS;
  782. if (ioctl(IspEnvironment->fdCom, TIOCMSET, &status) == 0)
  783. {
  784. DebugPrintf(3, "ioctl set ok, status = %X\n",status);
  785. }
  786. else
  787. {
  788. DebugPrintf(1, "ioctl set failed\n");
  789. }
  790. if (ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
  791. {
  792. DebugPrintf(3, "ioctl get ok, status = %X\n",status);
  793. }
  794. else
  795. {
  796. DebugPrintf(1, "ioctl get failed\n");
  797. }
  798. #endif // defined COMPILE_FOR_LINUX
  799. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  800. if (DTR) EscapeCommFunction(IspEnvironment->hCom, SETDTR);
  801. else EscapeCommFunction(IspEnvironment->hCom, CLRDTR);
  802. if (RTS) EscapeCommFunction(IspEnvironment->hCom, SETRTS);
  803. else EscapeCommFunction(IspEnvironment->hCom, CLRRTS);
  804. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  805. #if defined COMPILE_FOR_LPC21
  806. LPC_RESET(DTR);
  807. LPC_BSL(RTS);
  808. #endif
  809. DebugPrintf(3, "DTR (%d), RTS (%d)\n", DTR, RTS);
  810. }
  811. /***************************** ClearSerialPortBuffers********************/
  812. /** Empty the serial port buffers. Cleans things to a known state.
  813. */
  814. void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment)
  815. {
  816. #if defined COMPILE_FOR_LINUX
  817. /* variables to store the current tty state, create a new one */
  818. struct termios origtty, tty;
  819. /* store the current tty settings */
  820. tcgetattr(IspEnvironment->fdCom, &origtty);
  821. // Flush input and output buffers
  822. tty=origtty;
  823. tcsetattr(IspEnvironment->fdCom, TCSAFLUSH, &tty);
  824. /* reset the tty to its original settings */
  825. tcsetattr(IspEnvironment->fdCom, TCSADRAIN, &origtty);
  826. #endif // defined COMPILE_FOR_LINUX
  827. #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  828. PurgeComm(IspEnvironment->hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  829. #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
  830. }
  831. #endif // !defined COMPILE_FOR_LPC21
  832. #if defined COMPILE_FOR_LINUX
  833. /***************************** Sleep ************************************/
  834. /** Provide linux replacement for windows function.
  835. \param [in] Milliseconds the time to wait for in milliseconds.
  836. */
  837. void Sleep(unsigned long MilliSeconds)
  838. {
  839. usleep(MilliSeconds*1000); //convert to microseconds
  840. }
  841. #endif // defined COMPILE_FOR_LINUX
  842. #if defined COMPILE_FOR_LPC21
  843. /** Provide linux replacement for windows function.
  844. \note I implement that one in my private header file today...
  845. \param [in] Milliseconds the time to wait for in milliseconds.
  846. */
  847. /*static void Sleep(unsigned long MilliSeconds)
  848. {
  849. # warning Sleep function not implemented
  850. }
  851. */
  852. #endif // defined COMPILE_FOR_LPC21
  853. /************* Applicationlayer. */
  854. #if !defined COMPILE_FOR_LPC21
  855. /***************************** DebugPrintf ******************************/
  856. /** Prints a debug string depending the current debug level. The higher
  857. the debug level the more detail that will be printed. Each print
  858. has an associated level, the higher the level the more detailed the
  859. debugging information being sent.
  860. \param [in] level the debug level of the print statement, if the level
  861. is less than or equal to the current debug level it will be printed.
  862. \param [in] fmt a standard printf style format string.
  863. \param [in] ... the usual printf parameters.
  864. */
  865. #if !defined INTEGRATED_IN_WIN_APP
  866. void DebugPrintf(int level, const char *fmt, ...)
  867. {
  868. va_list ap;
  869. if (level <= debug_level)
  870. {
  871. char pTemp[2000];
  872. va_start(ap, fmt);
  873. //vprintf(fmt, ap);
  874. vsprintf(pTemp, fmt, ap);
  875. TRACE(pTemp);
  876. va_end(ap);
  877. fflush(stdout);
  878. }
  879. }
  880. #endif
  881. #endif // !defined COMPILE_FOR_LPC21
  882. /***************************** ReceiveComPort ***************************/
  883. /** Receives a buffer from the open com port. Returns when the buffer is
  884. filled, the numer of requested linefeeds has been received or the timeout
  885. period has passed
  886. \param [in] ISPEnvironment.
  887. \param [out] Answer buffer to hold the bytes read from the serial port.
  888. \param [in] MaxSize the size of buffer pointed to by Answer.
  889. \param [out] RealSize pointer to a long that returns the amout of the
  890. buffer that is actually used.
  891. \param [in] WantedNr0x0A the maximum number of linefeeds to accept before
  892. returning.
  893. \param [in] timeOutMilliseconds the maximum amount of time to wait before
  894. reading with an incomplete buffer.
  895. */
  896. void ReceiveComPort(ISP_ENVIRONMENT *IspEnvironment,
  897. const char *Ans, unsigned long MaxSize,
  898. unsigned long *RealSize, unsigned long WantedNr0x0A,
  899. unsigned timeOutMilliseconds)
  900. {
  901. unsigned long tmp_realsize;
  902. unsigned long nr_of_0x0A = 0;
  903. unsigned long nr_of_0x0D = 0;
  904. int eof = 0;
  905. unsigned long p;
  906. unsigned char *Answer;
  907. char tmp_string[32];
  908. Answer = (unsigned char*) Ans;
  909. SerialTimeoutSet(IspEnvironment, timeOutMilliseconds);
  910. (*RealSize) = 0;
  911. do
  912. {
  913. ReceiveComPortBlock(IspEnvironment, Answer + (*RealSize), MaxSize - 1 - (*RealSize), &tmp_realsize);
  914. if (tmp_realsize != 0)
  915. {
  916. for (p = (*RealSize); p < (*RealSize) + tmp_realsize; p++)
  917. {
  918. if (Answer[p] == 0x0a)
  919. {
  920. nr_of_0x0A++;
  921. }
  922. else if (Answer[p] == 0x0d)
  923. {
  924. nr_of_0x0D++;
  925. }
  926. else if (((signed char) Answer[p]) < 0)
  927. {
  928. eof = 1;
  929. }
  930. }
  931. }
  932. (*RealSize) += tmp_realsize;
  933. } while (((*RealSize) < MaxSize) && (SerialTimeoutCheck(IspEnvironment) == 0) && (nr_of_0x0A < WantedNr0x0A) && (nr_of_0x0D < WantedNr0x0A) && !eof);
  934. Answer[(*RealSize)] = 0;
  935. sprintf(tmp_string, "Answer(Length=%ld): ", (*RealSize));
  936. DumpString(3, Answer, (*RealSize), tmp_string);
  937. }
  938. #if !defined COMPILE_FOR_LPC21
  939. /***************************** ReceiveComPortBlockComplete **************/
  940. /** Receives a fixed block from the open com port. Returns when the
  941. block is completely filled or the timeout period has passed
  942. \param [out] block buffer to hold the bytes read from the serial port.
  943. \param [in] size the size of the buffer pointed to by block.
  944. \param [in] timeOut the maximum amount of time to wait before guvung up on
  945. completing the read.
  946. \return 0 if successful, non-zero otherwise.
  947. */
  948. int ReceiveComPortBlockComplete(ISP_ENVIRONMENT *IspEnvironment,
  949. void *block, size_t size, unsigned timeout)
  950. {
  951. unsigned long realsize = 0, read;
  952. char *result;
  953. char tmp_string[32];
  954. result = (char*) block;
  955. SerialTimeoutSet(IspEnvironment, timeout);
  956. do
  957. {
  958. ReceiveComPortBlock(IspEnvironment, result + realsize, size - realsize, &read);
  959. realsize += read;
  960. } while ((realsize < size) && (SerialTimeoutCheck(IspEnvironment) == 0));
  961. sprintf(tmp_string, "Answer(Length=%ld): ", realsize);
  962. DumpString(3, result, realsize, tmp_string);
  963. if (realsize != size)
  964. {
  965. return 1;
  966. }
  967. return 0;
  968. }
  969. /***************************** ReadArguments ****************************/
  970. /** Reads the command line arguments and parses it for the various
  971. options. Uses the same arguments as main. Used to separate the command
  972. line parsing from main and improve its readability. This should also make
  973. it easier to modify the command line parsing in the future.
  974. \param [in] argc the number of arguments.
  975. \param [in] argv an array of pointers to the arguments.
  976. */
  977. static void ReadArguments(ISP_ENVIRONMENT *IspEnvironment, unsigned int argc, char *argv[])
  978. {
  979. unsigned int i;
  980. if (argc >= 5)
  981. {
  982. for (i = 1; i < argc - 3; i++)
  983. {
  984. if (stricmp(argv[i], "-wipe") == 0)
  985. {
  986. IspEnvironment->WipeDevice = 1;
  987. DebugPrintf(3, "Wipe entire device before writing.\n");
  988. continue;
  989. }
  990. if (stricmp(argv[i], "-bin") == 0)
  991. {
  992. IspEnvironment->FileFormat = FORMAT_BINARY;
  993. DebugPrintf(3, "Binary format file input.\n");
  994. continue;
  995. }
  996. if (stricmp(argv[i], "-hex") == 0)
  997. {
  998. IspEnvironment->FileFormat = FORMAT_HEX;
  999. DebugPrintf(3, "Hex format file input.\n");
  1000. continue;
  1001. }
  1002. if (stricmp(argv[i], "-logfile") == 0)
  1003. {
  1004. IspEnvironment->LogFile = 1;
  1005. DebugPrintf(3, "Log terminal output.\n");
  1006. continue;
  1007. }
  1008. if (stricmp(argv[i], "-detectonly") == 0)
  1009. {
  1010. IspEnvironment->DetectOnly = 1;
  1011. IspEnvironment->ProgramChip = 0;
  1012. DebugPrintf(3, "Only detect LPC chip part id.\n");
  1013. continue;
  1014. }
  1015. if(strnicmp(argv[i],"-debug", 6) == 0)
  1016. {
  1017. char* num;
  1018. num = argv[i] + 6;
  1019. while(*num && isdigit(*num) == 0) num++;
  1020. if(isdigit(*num) != 0) debug_level = atoi( num);
  1021. else debug_level = 4;
  1022. DebugPrintf(3, "Turn on debug, level: %d.\n", debug_level);
  1023. continue;
  1024. }
  1025. if (stricmp(argv[i], "-DoNotStart") == 0)
  1026. {
  1027. IspEnvironment->DoNotStart = 1;
  1028. DebugPrintf(3, "Do NOT start MCU after programming.\n");
  1029. continue;
  1030. }
  1031. if (stricmp(argv[i], "-control") == 0)
  1032. {
  1033. IspEnvironment->ControlLines = 1;
  1034. DebugPrintf(3, "Use RTS/DTR to control target state.\n");
  1035. continue;
  1036. }
  1037. if (stricmp(argv[i], "-controlswap") == 0)
  1038. {
  1039. IspEnvironment->ControlLinesSwapped = 1;
  1040. DebugPrintf(3, "Use RTS to control reset, and DTR to control P0.14(ISP).\n");
  1041. continue;
  1042. }
  1043. if (stricmp(argv[i], "-controlinv") == 0)
  1044. {
  1045. IspEnvironment->ControlLinesInverted = 1;
  1046. DebugPrintf(3, "Invert state of RTS & DTR (0=true/assert/set, 1=false/deassert/clear).\n");
  1047. continue;
  1048. }
  1049. if (stricmp(argv[i], "-halfduplex") == 0)
  1050. {
  1051. IspEnvironment->HalfDuplex = 1;
  1052. DebugPrintf(3, "halfduplex serial communication.\n");
  1053. continue;
  1054. }
  1055. if (stricmp(argv[i], "-ADARM") == 0)
  1056. {
  1057. IspEnvironment->micro = ANALOG_DEVICES_ARM;
  1058. DebugPrintf(2, "Target: Analog Devices.\n");
  1059. continue;
  1060. }
  1061. if (stricmp(argv[i], "-NXPARM") == 0 || stricmp(argv[i], "-PHILIPSARM") == 0)
  1062. {
  1063. IspEnvironment->micro = NXP_ARM;
  1064. DebugPrintf(2, "Target: NXP.\n");
  1065. continue;
  1066. }
  1067. if (stricmp(argv[i], "-Verify") == 0)
  1068. {
  1069. IspEnvironment->Verify = 1;
  1070. DebugPrintf(2, "Verify after copy RAM to Flash.\n");
  1071. continue;
  1072. }
  1073. #ifdef INTEGRATED_IN_WIN_APP
  1074. if (stricmp(argv[i], "-nosync") == 0)
  1075. {
  1076. IspEnvironment->NoSync = 1;
  1077. DebugPrintf(2, "Performing no syncing, already done.\n");
  1078. continue;
  1079. }
  1080. #endif
  1081. #ifdef TERMINAL_SUPPORT
  1082. if (CheckTerminalParameters(IspEnvironment, argv[i]))
  1083. {
  1084. continue;
  1085. }
  1086. #endif
  1087. if(*argv[i] == '-') DebugPrintf( 2, "Unknown command line option: \"%s\"\n", argv[i]);
  1088. else
  1089. {
  1090. int ret_val;
  1091. if(IspEnvironment->FileFormat == FORMAT_HEX)
  1092. {
  1093. ret_val = AddFileHex(IspEnvironment, argv[i]);
  1094. }
  1095. else
  1096. {
  1097. ret_val = AddFileBinary(IspEnvironment, argv[i]);
  1098. }
  1099. if( ret_val != 0)
  1100. {
  1101. DebugPrintf( 2, "Unknown command line option: \"%s\"\n", argv[i]);
  1102. }
  1103. }
  1104. }
  1105. // Newest cygwin delivers a '\x0d' at the end of argument
  1106. // when calling lpc21isp from batch file
  1107. for (i = 0; i < strlen(argv[argc - 1]) && i < (sizeof(IspEnvironment->StringOscillator) - 1) &&
  1108. argv[argc - 1][i] >= '0' && argv[argc - 1][i] <= '9'; i++)
  1109. {
  1110. IspEnvironment->StringOscillator[i] = argv[argc - 1][i];
  1111. }
  1112. IspEnvironment->StringOscillator[i] = 0;
  1113. IspEnvironment->serial_port = argv[argc - 3];
  1114. IspEnvironment->baud_rate = argv[argc - 2];
  1115. }
  1116. if (argc < 5)
  1117. {
  1118. debug_level = (debug_level < 2) ? 2 : debug_level;
  1119. }
  1120. if (argc < 5)
  1121. {
  1122. DebugPrintf(2, "\n"
  1123. "Portable command line ISP\n"
  1124. "for NXP LPC1000 / LPC2000 family and Analog Devices ADUC 70xx\n"
  1125. "Version " VERSION_STR " compiled for " COMPILED_FOR ": " __DATE__ ", " __TIME__ "\n"
  1126. "Copyright (c) by Martin Maurer, 2003-2011, Email: Martin.Maurer@clibb.de\n"
  1127. "Portions Copyright (c) by Aeolus Development 2004, www.aeolusdevelopment.com\n"
  1128. "\n");
  1129. DebugPrintf(1, "Syntax: lpc21isp [Options] file[ file[ ...]] comport baudrate Oscillator_in_kHz\n\n"
  1130. "Example: lpc21isp test.hex com1 115200 14746\n\n"
  1131. "Options: -bin for uploading binary file\n"
  1132. " -hex for uploading file in intel hex format (default)\n"
  1133. " -term for starting terminal after upload\n"
  1134. " -termonly for starting terminal without an upload\n"
  1135. " -localecho for local echo in terminal\n"
  1136. " -detectonly detect only used LPC chiptype (NXPARM only)\n"
  1137. " -debug0 for no debug\n"
  1138. " -debug3 for progress info only\n"
  1139. " -debug5 for full debug\n"
  1140. " -donotstart do not start MCU after download\n"
  1141. " -try<n> try n times to synchronise\n"
  1142. " -wipe Erase entire device before upload\n"
  1143. " -control for controlling RS232 lines for easier booting\n"
  1144. " (Reset = DTR, EnableBootLoader = RTS)\n"
  1145. #ifdef INTEGRATED_IN_WIN_APP
  1146. " -nosync Do not synchronize device via '?'\n"
  1147. #endif
  1148. " -controlswap swap RS232 control lines\n"
  1149. " (Reset = RTS, EnableBootLoader = DTR)\n"
  1150. " -controlinv Invert state of RTS & DTR \n"
  1151. " (0=true/assert/set, 1=false/deassert/clear).\n"
  1152. " -verify Verify the data in Flash after every writes to\n"
  1153. " sector. To detect errors in writing to Flash ROM\n"
  1154. " -logfile for enabling logging of terminal output to lpc21isp.log\n"
  1155. " -halfduplex use halfduplex serial communication (i.e. with K-Line)\n"
  1156. " -ADARM for downloading to an Analog Devices\n"
  1157. " ARM microcontroller ADUC70xx\n"
  1158. " -NXPARM for downloading to a NXP LPC1xxx/LPC2xxx (default)\n");
  1159. exit(1);
  1160. }
  1161. if (IspEnvironment->micro == NXP_ARM)
  1162. {
  1163. // If StringOscillator is bigger than 100 MHz, there seems to be something wrong
  1164. if (strlen(IspEnvironment->StringOscillator) > 5)
  1165. {
  1166. DebugPrintf(1, "Invalid crystal frequency %s\n", IspEnvironment->StringOscillator);
  1167. exit(1);
  1168. }
  1169. }
  1170. }
  1171. /***************************** ResetTarget ******************************/
  1172. /** Resets the target leaving it in either download (program) mode or
  1173. run mode.
  1174. \param [in] mode the mode to leave the target in.
  1175. */
  1176. void ResetTarget(ISP_ENVIRONMENT *IspEnvironment, TARGET_MODE mode)
  1177. {
  1178. if (IspEnvironment->ControlLines)
  1179. {
  1180. switch (mode)
  1181. {
  1182. /* Reset and jump to boot loader. */
  1183. case PROGRAM_MODE:
  1184. ControlModemLines(IspEnvironment, 1, 1);
  1185. Sleep(100);
  1186. ClearSerialPortBuffers(IspEnvironment);
  1187. Sleep(100);
  1188. ControlModemLines(IspEnvironment, 0, 1);
  1189. //Longer delay is the Reset signal is conected to an external rest controller
  1190. Sleep(500);
  1191. // Clear the RTS line after having reset the micro
  1192. // Needed for the "GO <Address> <Mode>" ISP command to work */
  1193. ControlModemLines(IspEnvironment, 0, 0);
  1194. break;
  1195. /* Reset and start uploaded program */
  1196. case RUN_MODE:
  1197. ControlModemLines(IspEnvironment, 1, 0);
  1198. Sleep(100);
  1199. ClearSerialPortBuffers(IspEnvironment);
  1200. Sleep(100);
  1201. ControlModemLines(IspEnvironment, 0, 0);
  1202. Sleep(100);
  1203. break;
  1204. }
  1205. }
  1206. }
  1207. /***************************** Ascii2Hex ********************************/
  1208. /** Converts a hex character to its equivalent number value. In case of an
  1209. error rather abruptly terminates the program.
  1210. \param [in] c the hex digit to convert.
  1211. \return the value of the hex digit.
  1212. */
  1213. static unsigned char Ascii2Hex(unsigned char c)
  1214. {
  1215. if (c >= '0' && c <= '9')
  1216. {
  1217. return (unsigned char)(c - '0');
  1218. }
  1219. if (c >= 'A' && c <= 'F')
  1220. {
  1221. return (unsigned char)(c - 'A' + 10);
  1222. }
  1223. if (c >= 'a' && c <= 'f')
  1224. {
  1225. return (unsigned char)(c - 'a' + 10);
  1226. }
  1227. DebugPrintf(1, "Wrong Hex-Nibble %c (%02X)\n", c, c);
  1228. exit(1);
  1229. return 0; // this "return" will never be reached, but some compilers give a warning if it is not present
  1230. }
  1231. /***************************** AddFileHex *******************************/
  1232. /** Add a file to the list of files to read in, flag it as hex format.
  1233. \param [in] IspEnvironment Programming environment.
  1234. \param [in] arg The argument that was passed to the program as a file name.
  1235. \return 0 on success, an error code otherwise.
  1236. */
  1237. static int AddFileHex(ISP_ENVIRONMENT *IspEnvironment, const char *arg)
  1238. {
  1239. FILE_LIST *entry;
  1240. // Add file to list. If cannot allocate storage for node return an error.
  1241. entry = malloc(sizeof(FILE_LIST));
  1242. if( entry == 0)
  1243. {
  1244. DebugPrintf(1, "Error %d Could not allocated memory for file node %s\n", ERR_ALLOC_FILE_LIST, arg);
  1245. return ERR_ALLOC_FILE_LIST;
  1246. }
  1247. // Build up entry and insert it at the start of the list.
  1248. entry->name = arg;
  1249. entry->prev = IspEnvironment->f_list;
  1250. entry->hex_flag = 1;
  1251. IspEnvironment->f_list = entry;
  1252. return 0; // Success.
  1253. }
  1254. /***************************** AddFileBinary ****************************/
  1255. /** Add a file to the list of files to read in, flag it as binary format.
  1256. \param [in] IspEnvironment Programming environment.
  1257. \param [in] arg The argument that was passed to the program as a file name.
  1258. \return 0 on success, an error code otherwise.
  1259. */
  1260. static int AddFileBinary(ISP_ENVIRONMENT *IspEnvironment, const char *arg)
  1261. {
  1262. FILE_LIST *entry;
  1263. // Add file to list. If cannot allocate storage for node return an error.
  1264. entry = malloc(sizeof(FILE_LIST));
  1265. if( entry == 0)
  1266. {
  1267. DebugPrintf( 1, "Error %d Could not allocated memory for file node %s\n", ERR_ALLOC_FILE_LIST, arg);
  1268. return ERR_ALLOC_FILE_LIST;
  1269. }
  1270. // Build up entry and insert it at the start of the list.
  1271. entry->name = arg;
  1272. entry->prev = IspEnvironment->f_list;
  1273. entry->hex_flag = 0;
  1274. IspEnvironment->f_list = entry;
  1275. return 0; // Success.
  1276. }
  1277. #if 0
  1278. void ReadHexFile(ISP_ENVIRONMENT *IspEnvironment)
  1279. {
  1280. LoadFile(IspEnvironment);
  1281. if (IspEnvironment->BinaryLength)
  1282. {
  1283. BINARY* FileContent = IspEnvironment->FileContent;
  1284. unsigned long Pos;
  1285. unsigned char RecordLength;
  1286. unsigned short RecordAddress;
  1287. unsigned long RealAddress = 0;
  1288. unsigned char RecordType;
  1289. unsigned char Hexvalue;
  1290. unsigned long StartAddress;
  1291. int BinaryOffsetDefined = 0;
  1292. unsigned char i;
  1293. DebugPrintf(3, "Converting file %s to binary format...\n", IspEnvironment->input_file);
  1294. Pos = 0;
  1295. while (Pos < IspEnvironment->BinaryLength)
  1296. {
  1297. if (FileContent[Pos] == '\r')
  1298. {
  1299. Pos++;
  1300. continue;
  1301. }
  1302. if (FileContent[Pos] == '\n')
  1303. {
  1304. Pos++;
  1305. continue;
  1306. }
  1307. if (FileContent[Pos] != ':')
  1308. {
  1309. DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
  1310. exit(1);
  1311. }
  1312. Pos++;
  1313. RecordLength = Ascii2Hex(FileContent[Pos++]);
  1314. RecordLength <<= 4;
  1315. RecordLength |= Ascii2Hex(FileContent[Pos++]);
  1316. DebugPrintf(4, "RecordLength = %02X\n", RecordLength);
  1317. RecordAddress = Ascii2Hex(FileContent[Pos++]);
  1318. RecordAddress <<= 4;
  1319. RecordAddress |= Ascii2Hex(FileContent[Pos++]);
  1320. RecordAddress <<= 4;
  1321. RecordAddress |= Ascii2Hex(FileContent[Pos++]);
  1322. RecordAddress <<= 4;
  1323. RecordAddress |= Ascii2Hex(FileContent[Pos++]);
  1324. DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);
  1325. RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;
  1326. DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);
  1327. RecordType = Ascii2Hex(FileContent[Pos++]);
  1328. RecordType <<= 4;
  1329. RecordType |= Ascii2Hex(FileContent[Pos++]);
  1330. DebugPrintf(4, "RecordType = %02X\n", RecordType);
  1331. if (RecordType == 0x00) // 00 - Data record
  1332. {
  1333. /*
  1334. * Binary Offset is defined as soon as first data record read
  1335. */
  1336. //BinaryOffsetDefined = 1;
  1337. // Memory for binary file big enough ?
  1338. while ((RealAddress + RecordLength - IspEnvironment->BinaryOffset) > IspEnvironment->BinaryMemSize)
  1339. {
  1340. IspEnvironment->BinaryMemSize <<= 1; // Double the size allocated !!!
  1341. IspEnvironment->BinaryContent = (BINARY*) realloc(IspEnvironment->BinaryContent, IspEnvironment->BinaryMemSize);
  1342. }
  1343. // We need to know, what the highest address is,
  1344. // how many bytes / sectors we must flash
  1345. if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
  1346. {
  1347. IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
  1348. DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
  1349. }
  1350. for (i = 0; i < RecordLength; i++)
  1351. {
  1352. Hexvalue = Ascii2Hex(FileContent[Pos++]);
  1353. Hexvalue <<= 4;
  1354. Hexvalue |= Ascii2Hex(FileContent[Pos++]);
  1355. IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
  1356. }
  1357. }
  1358. else if (RecordType == 0x01) // 01 - End of file record
  1359. {
  1360. break;
  1361. }
  1362. else if (RecordType == 0x02) // 02 - Extended segment address record
  1363. {
  1364. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1365. {
  1366. RealAddress <<= 4;
  1367. if (i == 0)
  1368. {
  1369. RealAddress = Ascii2Hex(FileContent[Pos++]);
  1370. }
  1371. else
  1372. {
  1373. RealAddress |= Ascii2Hex(FileContent[Pos++]);
  1374. }
  1375. }
  1376. RealAddress <<= 4;
  1377. }
  1378. else if (RecordType == 0x03) // 03 - Start segment address record
  1379. {
  1380. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1381. {
  1382. RealAddress <<= 4;
  1383. if (i == 0)
  1384. {
  1385. RealAddress = Ascii2Hex(FileContent[Pos++]);
  1386. }
  1387. else
  1388. {
  1389. RealAddress |= Ascii2Hex(FileContent[Pos++]);
  1390. }
  1391. }
  1392. RealAddress <<= 8;
  1393. }
  1394. else if (RecordType == 0x04) // 04 - Extended linear address record, used by IAR
  1395. {
  1396. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1397. {
  1398. RealAddress <<= 4;
  1399. if (i == 0)
  1400. {
  1401. RealAddress = Ascii2Hex(FileContent[Pos++]);
  1402. }
  1403. else
  1404. {
  1405. RealAddress |= Ascii2Hex(FileContent[Pos++]);
  1406. }
  1407. }
  1408. RealAddress <<= 16;
  1409. if (!BinaryOffsetDefined)
  1410. {
  1411. // set startaddress of BinaryContent
  1412. // use of LPC_FLASHMASK to allow a memory range, not taking the first
  1413. // [04] record as actual start-address.
  1414. IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
  1415. }
  1416. else
  1417. {
  1418. if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
  1419. {
  1420. DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n"
  1421. "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
  1422. IspEnvironment->BinaryOffset, RealAddress);
  1423. exit(1);
  1424. }
  1425. }
  1426. }
  1427. else if (RecordType == 0x05) // 05 - Start linear address record
  1428. {
  1429. StartAddress = 0;
  1430. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1431. {
  1432. StartAddress <<= 4;
  1433. if (i == 0)
  1434. {
  1435. StartAddress = Ascii2Hex(FileContent[Pos++]);
  1436. }
  1437. else
  1438. {
  1439. StartAddress |= Ascii2Hex(FileContent[Pos++]);
  1440. }
  1441. }
  1442. DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
  1443. IspEnvironment->StartAddress = StartAddress;
  1444. }
  1445. while (FileContent[Pos++] != 0x0a) // Search till line end
  1446. {
  1447. }
  1448. }
  1449. DebugPrintf(2, "\tconverted to binary format...\n");
  1450. // When debugging is switched on, output result of conversion to file debugout.bin
  1451. if (debug_level >= 4)
  1452. {
  1453. int fdout;
  1454. fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
  1455. write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
  1456. close(fdout);
  1457. }
  1458. }
  1459. }
  1460. #endif // #if 0
  1461. /***************************** LoadFile *********************************/
  1462. /** Loads the requested file to download into memory.
  1463. \param [in] IspEnvironment structure containing input filename
  1464. \param [in] filename the name of the file to read in.
  1465. \param [in] FileFormat the format of the file to read in (FORMAT_HEX or FORMAT_BINARY)
  1466. \return 0 if successful, otherwise an error code.
  1467. */
  1468. static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat)
  1469. {
  1470. int fd;
  1471. int i;
  1472. int BinaryOffsetDefined;
  1473. unsigned long Pos;
  1474. unsigned long FileLength;
  1475. BINARY *FileContent; /**< Used to store the content of a hex */
  1476. /* file before converting to binary. */
  1477. unsigned long BinaryMemSize;
  1478. fd = open(filename, O_RDONLY | O_BINARY);
  1479. if (fd == -1)
  1480. {
  1481. DebugPrintf(1, "Can't open file %s\n", filename);
  1482. return ERR_FILE_OPEN_HEX;
  1483. }
  1484. FileLength = lseek(fd, 0L, 2); // Get file size
  1485. if (FileLength == (size_t)-1)
  1486. {
  1487. DebugPrintf(1, "\nFileLength = -1 !?!\n");
  1488. return ERR_FILE_SIZE_HEX;
  1489. }
  1490. lseek(fd, 0L, 0);
  1491. // Just read the entire file into memory to parse.
  1492. FileContent = (BINARY*) malloc(FileLength);
  1493. if( FileContent == 0)
  1494. {
  1495. DebugPrintf( 1, "\nCouldn't allocate enough memory for file.\n");
  1496. return ERR_FILE_ALLOC_HEX;
  1497. }
  1498. BinaryOffsetDefined = 0;
  1499. BinaryMemSize = IspEnvironment->BinaryLength;
  1500. read(fd, FileContent, FileLength);
  1501. close(fd);
  1502. DebugPrintf(2, "File %s:\n\tloaded...\n", filename);
  1503. // Intel-Hex -> Binary Conversion
  1504. if (FileFormat == FORMAT_HEX)
  1505. {
  1506. unsigned char RecordLength;
  1507. unsigned short RecordAddress;
  1508. unsigned long RealAddress = 0;
  1509. unsigned char RecordType;
  1510. unsigned char Hexvalue;
  1511. unsigned long StartAddress;
  1512. DebugPrintf(3, "Converting file %s to binary format...\n", filename);
  1513. Pos = 0;
  1514. while (Pos < FileLength)
  1515. {
  1516. if (FileContent[Pos] == '\r')
  1517. {
  1518. Pos++;
  1519. continue;
  1520. }
  1521. if (FileContent[Pos] == '\n')
  1522. {
  1523. Pos++;
  1524. continue;
  1525. }
  1526. if (FileContent[Pos] != ':')
  1527. {
  1528. DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
  1529. exit(1);
  1530. }
  1531. Pos++;
  1532. RecordLength = Ascii2Hex(FileContent[Pos++]);
  1533. RecordLength <<= 4;
  1534. RecordLength |= Ascii2Hex(FileContent[Pos++]);
  1535. DebugPrintf(4, "RecordLength = %02X\n", RecordLength);
  1536. RecordAddress = Ascii2Hex(FileContent[Pos++]);
  1537. RecordAddress <<= 4;
  1538. RecordAddress |= Ascii2Hex(FileContent[Pos++]);
  1539. RecordAddress <<= 4;
  1540. RecordAddress |= Ascii2Hex(FileContent[Pos++]);
  1541. RecordAddress <<= 4;
  1542. RecordAddress |= Ascii2Hex(FileContent[Pos++]);
  1543. DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);
  1544. RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;
  1545. DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);
  1546. RecordType = Ascii2Hex(FileContent[Pos++]);
  1547. RecordType <<= 4;
  1548. RecordType |= Ascii2Hex(FileContent[Pos++]);
  1549. DebugPrintf(4, "RecordType = %02X\n", RecordType);
  1550. if (RecordType == 0x00) // 00 - Data record
  1551. {
  1552. /*
  1553. * Binary Offset is defined as soon as first data record read
  1554. */
  1555. BinaryOffsetDefined = 1;
  1556. // Memory for binary file big enough ?
  1557. while (RealAddress + RecordLength - IspEnvironment->BinaryOffset > BinaryMemSize)
  1558. {
  1559. if(!BinaryMemSize) BinaryMemSize = FileLength * 2;
  1560. else BinaryMemSize <<= 1;
  1561. IspEnvironment->BinaryContent = realloc(IspEnvironment->BinaryContent, BinaryMemSize);
  1562. }
  1563. // We need to know, what the highest address is,
  1564. // how many bytes / sectors we must flash
  1565. if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
  1566. {
  1567. IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
  1568. DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
  1569. }
  1570. for (i = 0; i < RecordLength; i++)
  1571. {
  1572. Hexvalue = Ascii2Hex(FileContent[Pos++]);
  1573. Hexvalue <<= 4;
  1574. Hexvalue |= Ascii2Hex(FileContent[Pos++]);
  1575. IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
  1576. }
  1577. }
  1578. else if (RecordType == 0x01) // 01 - End of file record
  1579. {
  1580. break;
  1581. }
  1582. else if (RecordType == 0x02) // 02 - Extended segment address record
  1583. {
  1584. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1585. {
  1586. RealAddress <<= 4;
  1587. if (i == 0)
  1588. {
  1589. RealAddress = Ascii2Hex(FileContent[Pos++]);
  1590. }
  1591. else
  1592. {
  1593. RealAddress |= Ascii2Hex(FileContent[Pos++]);
  1594. }
  1595. }
  1596. RealAddress <<= 4;
  1597. }
  1598. else if (RecordType == 0x03) // 03 - Start segment address record
  1599. {
  1600. unsigned long cs,ip;
  1601. StartAddress = 0;
  1602. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1603. {
  1604. StartAddress <<= 4;
  1605. if (i == 0)
  1606. {
  1607. StartAddress = Ascii2Hex(FileContent[Pos++]);
  1608. }
  1609. else
  1610. {
  1611. StartAddress |= Ascii2Hex(FileContent[Pos++]);
  1612. }
  1613. }
  1614. cs = StartAddress >> 16; //high part
  1615. ip = StartAddress & 0xffff; //low part
  1616. StartAddress = cs*16+ip; //segmented 20-bit space
  1617. DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
  1618. IspEnvironment->StartAddress = StartAddress;
  1619. }
  1620. else if (RecordType == 0x04) // 04 - Extended linear address record, used by IAR
  1621. {
  1622. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1623. {
  1624. RealAddress <<= 4;
  1625. if (i == 0)
  1626. {
  1627. RealAddress = Ascii2Hex(FileContent[Pos++]);
  1628. }
  1629. else
  1630. {
  1631. RealAddress |= Ascii2Hex(FileContent[Pos++]);
  1632. }
  1633. }
  1634. RealAddress <<= 16;
  1635. if (!BinaryOffsetDefined)
  1636. {
  1637. // set startaddress of BinaryContent
  1638. // use of LPC_FLASHMASK to allow a memory range, not taking the first
  1639. // [04] record as actual start-address.
  1640. IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
  1641. }
  1642. else
  1643. {
  1644. if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
  1645. {
  1646. DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n");
  1647. DebugPrintf(1, "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
  1648. IspEnvironment->BinaryOffset, RealAddress);
  1649. return ERR_MEMORY_RANGE;
  1650. }
  1651. }
  1652. }
  1653. else if (RecordType == 0x05) // 05 - Start linear address record
  1654. {
  1655. StartAddress = 0;
  1656. for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
  1657. {
  1658. StartAddress <<= 4;
  1659. if (i == 0)
  1660. {
  1661. StartAddress = Ascii2Hex(FileContent[Pos++]);
  1662. }
  1663. else
  1664. {
  1665. StartAddress |= Ascii2Hex(FileContent[Pos++]);
  1666. }
  1667. }
  1668. DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
  1669. IspEnvironment->StartAddress = StartAddress;
  1670. }
  1671. else
  1672. {
  1673. free( FileContent);
  1674. DebugPrintf( 1, "Error %d RecordType %02X not yet implemented\n", ERR_RECORD_TYPE_LOADFILE, RecordType);
  1675. return( ERR_RECORD_TYPE_LOADFILE);
  1676. }
  1677. while (FileContent[Pos++] != 0x0a) // Search till line end
  1678. {
  1679. }
  1680. }
  1681. DebugPrintf(2, "\tconverted to binary format...\n");
  1682. // When debugging is switched on, output result of conversion to file debugout.bin
  1683. if (debug_level >= 4)
  1684. {
  1685. int fdout;
  1686. fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
  1687. write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
  1688. close(fdout);
  1689. }
  1690. free( FileContent); // Done with file contents
  1691. }
  1692. else // FORMAT_BINARY
  1693. {
  1694. IspEnvironment->BinaryContent = FileContent;
  1695. IspEnvironment->BinaryLength = FileLength;
  1696. }
  1697. DebugPrintf(2, "\timage size : %ld\n", IspEnvironment->BinaryLength);
  1698. return 0;
  1699. }
  1700. /***************************** LoadFiles1 ********************************/
  1701. /** Loads the requested files to download into memory.
  1702. \param [in] IspEnvironment structure containing input filename(s).
  1703. \param [in] file simple linked list of files to read
  1704. \return 0 if successful, otherwise an error code.
  1705. */
  1706. static int LoadFiles1(ISP_ENVIRONMENT *IspEnvironment, const FILE_LIST *file)
  1707. {
  1708. int ret_val;
  1709. if(!file || !file->prev)
  1710. {
  1711. return -1;
  1712. }
  1713. DebugPrintf( 3, "Follow file list %s\n", file->name);
  1714. ret_val = LoadFiles1( IspEnvironment, file->prev);
  1715. if( ret_val != 0)
  1716. {
  1717. return ret_val;
  1718. }
  1719. DebugPrintf( 3, "Attempt to read File %s\n", file->name);
  1720. if(file->hex_flag != 0)
  1721. {
  1722. ret_val = LoadFile(IspEnvironment, file->name, FORMAT_HEX);
  1723. }
  1724. else
  1725. {
  1726. ret_val = LoadFile(IspEnvironment, file->name, FORMAT_BINARY);
  1727. }
  1728. if( ret_val != 0)
  1729. {
  1730. return ret_val;
  1731. }
  1732. return 0;
  1733. }
  1734. /***************************** LoadFiles ********************************/
  1735. /** Loads the requested files to download into memory.
  1736. \param [in] IspEnvironment structure containing input filename(s).
  1737. \param [in] file simple linked list of files to read
  1738. \return 0 if successful, otherwise an error code.
  1739. */
  1740. static int LoadFiles(ISP_ENVIRONMENT *IspEnvironment)
  1741. {
  1742. int ret_val;
  1743. ret_val = LoadFiles1(IspEnvironment, IspEnvironment->f_list);
  1744. if( ret_val != 0)
  1745. {
  1746. exit(1); // return ret_val;
  1747. }
  1748. DebugPrintf( 2, "Image size : %ld\n", IspEnvironment->BinaryLength);
  1749. // check length to flash for correct alignment, can happen with broken ld-scripts
  1750. if (IspEnvironment->BinaryLength % 4 != 0)
  1751. {
  1752. unsigned long NewBinaryLength = ((IspEnvironment->BinaryLength + 3)/4) * 4;
  1753. DebugPrintf( 2, "Warning: data not aligned to 32 bits, padded (length was %lX, now %lX)\n", IspEnvironment->BinaryLength, NewBinaryLength);
  1754. IspEnvironment->BinaryLength = NewBinaryLength;
  1755. }
  1756. // When debugging is switched on, output result of conversion to file debugout.bin
  1757. if(debug_level >= 4)
  1758. {
  1759. int fdout;
  1760. DebugPrintf( 1, "Dumping image file.\n");
  1761. fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
  1762. write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
  1763. close(fdout);
  1764. }
  1765. return 0;
  1766. }
  1767. #endif // !defined COMPILE_FOR_LPC21
  1768. #ifndef COMPILE_FOR_LPC21
  1769. int PerformActions(ISP_ENVIRONMENT *IspEnvironment)
  1770. {
  1771. int downloadResult = -1;
  1772. DebugPrintf(2, "lpc21isp version " VERSION_STR "\n");
  1773. /* Download requested, read in the input file. */
  1774. if (IspEnvironment->ProgramChip)
  1775. {
  1776. LoadFiles(IspEnvironment);
  1777. }
  1778. OpenSerialPort(IspEnvironment); /* Open the serial port to the microcontroller. */
  1779. ResetTarget(IspEnvironment, PROGRAM_MODE);
  1780. ClearSerialPortBuffers(IspEnvironment);
  1781. /* Perform the requested download. */
  1782. if (IspEnvironment->ProgramChip || IspEnvironment->DetectOnly)
  1783. {
  1784. switch (IspEnvironment->micro)
  1785. {
  1786. #ifdef LPC_SUPPORT
  1787. case NXP_ARM:
  1788. downloadResult = NxpDownload(IspEnvironment);
  1789. break;
  1790. #endif
  1791. #ifdef AD_SUPPORT
  1792. case ANALOG_DEVICES_ARM:
  1793. downloadResult = AnalogDevicesDownload(IspEnvironment);
  1794. break;
  1795. #endif
  1796. }
  1797. if (downloadResult != 0)
  1798. {
  1799. CloseSerialPort(IspEnvironment);
  1800. exit(downloadResult);
  1801. }
  1802. }
  1803. if (IspEnvironment->StartAddress == 0 || IspEnvironment->TerminalOnly)
  1804. {
  1805. /* Only reset target if startaddress = 0
  1806. * Otherwise stay with the running program as started in Download()
  1807. */
  1808. ResetTarget(IspEnvironment, RUN_MODE);
  1809. }
  1810. debug_level = 1; /* From now on there is no more debug output !! */
  1811. /* Therefore switch it off... */
  1812. #ifdef TERMINAL_SUPPORT
  1813. // Pass control to Terminal which will provide a terminal if one was asked for
  1814. // User asked for terminal emulation, provide a really dumb terminal.
  1815. Terminal(IspEnvironment);
  1816. #endif
  1817. CloseSerialPort(IspEnvironment); /* All done, close the serial port to the */
  1818. return 0;
  1819. }
  1820. #endif
  1821. /***************************** main *************************************/
  1822. /** main. Everything starts from here.
  1823. \param [in] argc the number of arguments.
  1824. \param [in] argv an array of pointers to the arguments.
  1825. */
  1826. #if !defined COMPILE_FOR_LPC21
  1827. #if defined INTEGRATED_IN_WIN_APP
  1828. int AppDoProgram(int argc, char *argv[])
  1829. #else
  1830. int main(int argc, char *argv[])
  1831. #endif
  1832. {
  1833. ISP_ENVIRONMENT IspEnvironment;
  1834. // Initialize debug level
  1835. debug_level = 2;
  1836. // Initialize ISP Environment
  1837. memset(&IspEnvironment, 0, sizeof(IspEnvironment)); // Clear the IspEnviroment to a known value
  1838. IspEnvironment.micro = NXP_ARM; // Default Micro
  1839. IspEnvironment.FileFormat = FORMAT_HEX; // Default File Format
  1840. IspEnvironment.ProgramChip = TRUE; // Default to Programming the chip
  1841. IspEnvironment.nQuestionMarks = 100;
  1842. IspEnvironment.DoNotStart = 0;
  1843. ReadArguments(&IspEnvironment, argc, argv); // Read and parse the command line
  1844. return PerformActions(&IspEnvironment); // Do as requested !
  1845. }
  1846. #endif // !defined COMPILE_FOR_LPC21
  1847. /***************************** DumpString ******************************/
  1848. /** Prints an area of memory to stdout. Converts non-printables to hex.
  1849. \param [in] level the debug level of the block to be dumped. If this is
  1850. less than or equal to the current debug level than the dump will happen
  1851. otherwise this just returns.
  1852. \param [in] b pointer to an area of memory.
  1853. \param [in] size the length of the memory block to print.
  1854. \param [in] prefix string is a pointer to a prefix string.
  1855. */
  1856. void DumpString(int level, const void *b, size_t size, const char *prefix_string)
  1857. {
  1858. size_t i;
  1859. const char * s = (const char*) b;
  1860. unsigned char c;
  1861. DebugPrintf(level, prefix_string);
  1862. DebugPrintf(level, "'");
  1863. for (i = 0; i < size; i++)
  1864. {
  1865. c = s[i];
  1866. if (c >= 0x20 && c <= 0x7e) /*isprint?*/
  1867. {
  1868. DebugPrintf(level, "%c", c);
  1869. }
  1870. else
  1871. {
  1872. DebugPrintf(level, "(%02X)", c);
  1873. }
  1874. }
  1875. DebugPrintf(level, "'\n");
  1876. }
  1877. #if !defined COMPILE_FOR_LPC21
  1878. int lpctest(char* FileName)
  1879. {
  1880. ISP_ENVIRONMENT IspEnvironment;
  1881. // Initialize debug level
  1882. debug_level = 2;
  1883. // Initialize ISP Environment
  1884. memset(&IspEnvironment, 0, sizeof(IspEnvironment)); // Clear the IspEnviroment to a known value
  1885. IspEnvironment.micro = NXP_ARM; // Default Micro
  1886. IspEnvironment.FileFormat = FORMAT_HEX; // Default File Format
  1887. IspEnvironment.ProgramChip = TRUE; // Default to Programming the chip
  1888. // IspEnvironment.input_file = FileName;
  1889. IspEnvironment.ControlLines = TRUE;
  1890. IspEnvironment.serial_port = "COM2";
  1891. IspEnvironment.baud_rate = "19200";
  1892. IspEnvironment.nQuestionMarks = 100;
  1893. IspEnvironment.DoNotStart = 0;
  1894. strcpy(IspEnvironment.StringOscillator, "25000");
  1895. return PerformActions(&IspEnvironment); // Do as requested !
  1896. }
  1897. #endif