1 /******************************************************************************
3 Project: Portable command line ISP for NXP LPC family
4 and Analog Devices ADUC70xx
8 Compiler: Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,
9 GCC Cygwin, GCC Linux, GCC ARM ELF
11 Author: Martin Maurer (Martin.Maurer@clibb.de)
13 Copyright: (c) Martin Maurer 2003-2013, All rights reserved
14 Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com
16 This file is part of lpc21isp.
18 lpc21isp is free software: you can redistribute it and/or modify
19 it under the terms of the GNU Lesser General Public License as published by
20 the Free Software Foundation, either version 3 of the License, or
23 lpc21isp is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU Lesser General Public License for more details.
28 You should have received a copy of the GNU Lesser General Public License
29 and GNU General Public License along with lpc21isp.
30 If not, see <http://www.gnu.org/licenses/>.
34 #if !defined __BORLANDC__
35 #include "StdAfx.h" // Precompiled Header for WIN32
37 #endif // defined(_WIN32)
38 #include "lpc21isp.h" // if using propriatory serial port communication (customize attached lpc21isp.h)
46 1.00 2004-01-08 Initial Version, tested for MSVC6/7 and GCC under Cygwin
47 1.01 2004-01-10 Porting to Linux (at least compiling must work)
48 1.02 2004-01-10 Implemented conversion intel hex format -> binary
49 1.03 2004-01-25 Preparation to upload to public website
50 1.04 2004-02-12 Merged in bugfixes by Soeren Gust
51 1.05 2004-03-14 Implement printing of error codes as text / strings
52 1.06 2004-03-09 Merged in bugfixes by Charles Manning:
53 The '?' sychronisation does not reliably respond to the first '?'.
55 The LPC2106 sometimes responds to the '?' by echoing them back.
56 This sometimes causes an attempt to match "?Synchonized".
57 Added code to strip off any leading '?'s.
58 Timeouts were too long.
59 Change from RTS/CTS to no flow control.
60 Done because many/most people will use only 3-wire comms.
61 Added some progress tracing.
62 1.07 2004-03-14 Implement handling of control lines for easier booting
63 1.08 2004-04-01 Bugfix for upload problem
64 1.09 2004-04-03 Redesign of upload routine
65 Now always 180 byte blocks are uploaded, to prevent
66 small junks in uuencoding
67 1.10 2004-04-03 Clear buffers before sending commands to LPC21xx,
68 this prevents synchronizing errors when previously loaded
69 program does a lot of output, so FIFO of PC runs full
70 1.11 2004-04-03 Small optimization for controlling reset line
71 otherwise termonly starts LPC twice, free PC buffers
72 1.12 2004-04-04 Add switch to enable logging terminal output to lpc21isp.log
73 1.13 2004-05-19 Merged in improvement by Charles Manning:
74 Instead of exiting the wrong hex file size is corrected
75 1.14 2004-07-07 Merged in improvement by Alex Holden:
76 Remove little/big endian dependancy
77 1.15 2004-09-27 Temporary improvement by Cyril Holweck:
78 Removed test (data echoed = data transmited) on the main
79 data transfert, since this was the biggest failure
80 reason and is covered by checksome anyway.
81 Added COMPILE_FOR_LPC21, to have target dump it's own
83 1.16 2004-10-09 Merged in bugfix / improvement by Sinelnikov Evgeny
84 I found out that Linux and Windows serial port initialization
85 are different with pinouts states. My board don't get
86 reset signal at first cycle of DTR pinout moving.
87 And I add this moving to initalization cycle.
88 1.17 2004-10-21 Changes by Cyril Holweck
89 Divide main, take out the real programming function, that can
90 also be used by a target to copy its own code to another.
91 1.18 2004-10-26 Changes by Cyril Holweck
92 Added a "G 0 A\r\n" at end of programming to run code.
93 1.19 2004-11-03 Changes by Robert Adsett
94 Add support for Analog Devices.
95 Separate file load from programming.
96 Change from a debug on/off flag to debug level
97 Remove if (debug) tests and replace with DebugPrintf
99 Change serial I/O and timing so that the system
100 dependancies are isolated to a few portability functions.
101 Add support for binary serial I/O.
103 1.20 2004-11-07 Preparation for multiport booting (factory support)
104 1.21 2004-11-08 Bugfix from Robert Adsett
105 BinaryLength was not initialized
106 1.22 2004-11-08 Changes from Cyril Holweck / Evgeny Sinelnikov
107 Forgotten IspEnvironment-> and bugfixes if COMPILE_FOR_LINUX
108 If COMPILE_FOR_LPC21, PhilipsDownload() 'acts as' main():
109 - it should not be static and should return int.
110 - no sub-function can use exit() but only return ()
111 Use 'char' instead of 'byte' ;)
112 1.23 2005-01-16 Build in automatic detection of LPC chiptype
113 (needed for 256 KByte support)
114 1.24B 2005-06-02 Changes by Thiadmer Riemersma: completed support for other
115 chip types (LPC213x series and others).
116 1.24C 2005-06-11 Changes by Thiadmer Riemersma: added the device ID codes for
117 chip types LPC2131 and LPC2132.
118 1.25 2005-06-19 Martin Maurer: Setup more parameters in DCB,
119 otherwise wrong code is downloaded (only Windows and Cygwin)
120 when a previous program has changed these parameters
121 Check exact string of "G 0 A\r\n0\r\n" instead of whole received buffer,
122 to prevent checking of already received by program start
123 (error on running program, but reports CMD_SUCCESS)
124 Add ifdefs for all baudrates (needed only for high baudrate,
125 which seem to be not available on Macs...)
126 1.26 2005-06-26 Martin Maurer:
127 Correct check again: "G 0 A\r\n0\r\n" is cutted, because of reboot
128 (error on running program, but reports CMD_SUCCESS)
129 1.27 2005-06-29 Martin Maurer:
130 Add LPC chip ID's (thanks to Robert from Philips) for
131 missing LPC213x and upcoming new LPC214x chips
132 (currently untested, because i don't have access to these chips,
133 please give me feedback !)
134 1.28 2005-07-27 Anders Rosvall / Embedded Artists AB:
135 Changed the reset timeout to 500 ms when entering the bootloader.
136 Some external reset controllers have quite long timeout periods,
137 so extening the timeout delay would be a good thing.
138 1.29 2005-09-14 Rob Jansen:
139 Added functionality to download to RAM and run from there.
140 In LoadFile() added record types 04 (Extended Linear Address Record)
141 and 05 (Start Linear Address Record), added address offset
142 (IspEnvironment->BinaryOffset) and start address (...->StartAddress).
143 Changed PhilipsDownload to skip all Flash prepare/erase/copy commands.
144 Note: Tested with VC7 only
145 1.30 2005-10-04 Rob Jansen:
146 - forgot to change the version string in 1.29
147 - Wrong text in LoadFile corrected (printed text mentions record type 05,
149 - Changed LoadFile to accept multiple record types 04
150 - Changed LoadFile to check on memory size, will not load more than x MB
151 if linear extended address records are used
152 1.31 2005-11-13 Martin Maurer: Thanks to Frank Gutmann
153 Updated number of sectors in device table
154 for LPC2194, LPC2292 and LPC2294
155 1.32 2005-12-02 Martin Maurer: Corrected missing control of RTS/DTR
156 in case user selected -termonly and -control
157 Small correction (typo in debug)
158 1.33 2006-10-01 Jean-Marc Koller:
159 Added support for MacOS X (difference on how to set termios baudrate).
160 1.34 2006-10-01 Cyril Holweck:
161 Made it compile again for lpc21isp
162 Added const keyword to constant variables to make it better
163 code for embeded target. (decrease RAM usage)
164 Replaced all regular call to printf() by DebugPrintf()
165 Removed call to scanf() (not much usefull and cost a lot to my target)
166 1.35 2006-22-01 Cyril Holweck
167 Added feature for LPC21: will start downloading at Sector 1 and upward,
168 to finish with Sector 0, the one containing the checksum controling BSL entry
169 1.36 2006-25-01 Cyril Holweck
170 PhilipsDownload() will now return a unique error code for each error
171 1.37 2006-10-03 Jeroen Domburg
172 Added LPC2103 (and only the 2103, I can't find the IDs for 2101/2102)
173 Corrected a loop which occured if the program completely fits in sector 0
174 1.38 2007-01-05 Ray Molenkamp
175 Added feature for LPC21: Wipe entire device before programming to enable
176 reflashing of chips with the lpc codeprotection feature enabled.
177 1.39 2007-01-12 Martin Maurer
178 Added initial support for new processors LPC23xx and LPC24xx
179 1.40 2007-01-22 Martin Maurer
180 Correction of chip id of LPC2458
181 1.41 2007-01-28 Jean-Marc Koller
182 Modified Terminal() to disable ECHO with termios only once, instead of
183 modifying and restoring termios in each getch and kbhit call (which caused
184 a strange echo behaviour in MacOS X).
185 1.42 2007-01-28 Rob Probin
186 Added -localecho command to allow local echoing in terminal mode for use
187 where target does not echo back keystrokes.
188 1.43 2007-01-29 Martin Maurer
189 Moved keyboard handling routines to own subroutines,
190 so they can be used during aborting synchronisation.
191 Newest cygwin made problems, StringOscillator always contained '\0x0d'
192 at the end, when calling lpc21isp from batch file
193 1.44 2007-02-23 Yang Yang
194 Added feature for LPC21: Verify the data in Flash after every writes
195 to sector. To detect errors in writing to Flash ROM.
196 1.45 2007-02-25 Martin Maurer
197 Replace printf syntax of DumpString by a simple pointer to a string
198 printf syntax is a nice thing, but it is not working :-(
199 and therefore makes debugging much more difficult...
200 Moved VERSION_STR to top of file to avoid possible cosmetical errors
201 1.46 2007-02-25 Martin Maurer
202 Again corrected debug output: should solve output of
203 (FFFFFFB5) instead of (B5)
204 1.47 2007-02-27 Robert Adsett
205 Raised timeout on AD send packet function.
206 1.48 2007-04-20 Martin Maurer
207 Thanks to Josef Wolf for preventing to overwrite over end of array
208 1.49 2007-10-16 New Option -halfduplex allow single wire using.
209 Implemented and tested only for Windows. Data Resend implemented.
210 1.50 2007-10-31 Changes by Simon Ellwood
211 Formated the code for readablity
212 Fixed some c++ compiler issues
213 1.51 2007-11-20 Changes by Simon Ellwood
214 Split into seperate files
215 Made more modular so when used in an embedded mode only the required code is built
216 1.52 2008-01-22 Changes by Manuel Koeppen
217 Made compileable again for linux and windows
218 Fixed bug in ClearSerialPortBuffers (linux)
219 1.53 2008-02-25 Changes by Michael Roth
220 Get priority of debug messages with -control right
221 1.54 2008-03-03 Martin Maurer
222 Try to bring lpc21isp back to a useable state in Windows, Cygwin, Linux and Mac OS.
223 Merged in changes by Erika Stefanini, which were done only for old version 1.49:
224 Added device ids for revision B chips
225 1.55 2008-03-03 Martin Maurer
226 Thanks to Fausto Marzoli, bugfix for compiling latest version under Linux
227 1.56 2008-04-01 Steve Franks
228 Integrate FreeBSD patch.
229 Add support for swapping and/or inverting RTS & DTR
230 1.57 2008-04-06 Mauricio Scaff
231 Changed OpenSerialPort to work with MacOS
232 Corrected the number of sectors in some 512K devices (28 instead of 27)
233 Added support for LPC2387 and LPC2388
234 Defined BL error 19 (Code Protected)
235 1.58 2008-05-10 Herbert Demmel dh2@demmel.com
236 I had the special requirement to integrate the program into my own Windows
237 software compiled with Borland C++ Builder 5. I had to do some minor changes
238 for Borland (see defined __BORLANDC__) and modified to code slightly to have
239 some simple callbacks for screen i/o (see define INTEGRATED_IN_WIN_APP).
240 Please note that I do *not* check / modify the part for AnalogDevices !!
241 Besides that I fixed some minor issues:
242 added dcb.fOutxCtsFlow = FALSE and dcb.fOutxDsrFlow = FALSE (sometimes required)
243 Now comparing one character less of answer to "Now launching ... code" command
244 1.59 2008-07-07 Peter Hayward
245 Fixed freeze under Windows XP SP2 by removing redundant call to SetCommMask.
246 1.60 2008-07-21 Martin Maurer
247 Added uptodate part ids for LPC2458, LPC2468 and LPC2478
248 Add comment "obsolete" for older part ids for LPC2458 and LPC2468
249 Add ", " between compile date and time
250 1.61 2008-10-21 Fausto Marzoli (thanks to Geoffrey Wossum for the patches)
251 Fix for compiling latest version under Linux and "ControlLinesSwapped" issue
252 1.62 2008-11-19 Martin Maurer
253 Added (untested) support for LPC2109
254 Added (untested) support for LPC2361 / LPC2362
255 Heavy update of part identification number of LPC23xx and LPC24xx
256 Correct bug, that hex file must exist, when "-detectonly" is used
257 Correct Makefile.vc: use /Fe instead of -o
258 1.63 2008-11-23 Martin Maurer
259 Changed to GNU Lesser General Public License
260 1.64 2009-01-19 Steve Franks
261 __FREEBSD__ changed to __FreeBSD__ at some point, plus other com port fixes
262 1.65 2009-03-26 Vito Marolda
263 Added pre-erasure of sector 0 to invalidate checksum before starting
264 modification of the other sectors, so that the bootloader restarts
265 if programming gets aborted while writing on a non-empty part.
266 1.66 2009-03-26 Vito Marolda
267 Corrected interpretation of intel hex record 03 which is execution start address
268 and not data segment address
269 1.67 2009-04-19 SASANO Takayoshi
271 1.68 2009-05-17 Martin Maurer
272 Merge in changes done by Bruno Quoitin (baudrate problem when __APPLE__ is used)
273 Remove TABs from source code and replaced them with spaces
274 1.69 2009-06-18 Martin Maurer
275 Add support for LPC17xx devices
276 1.70 2009-06-29 Martin Maurer
277 Further improvement of LPC17xx support
278 Workaround for booter (4.1) of LPC17xx, which does not echo all sent characters (0D,0A,...)
279 ISP command GO seems to be broken:
280 Sending 'G 196 T(0A)'
281 Answer(Length=15): 'G 196 T(0A)0(0D)(0A)'
282 leads to 'prefetch_abort_exception(0D)(0A)1FFF07A5'
283 No solution known...need your help here...
284 Manual workaround: Use DTR and RTS toggling to start application (e.g. 2 batch files)
285 1.71 2009-07-19 Martin Maurer
286 Added LPC17xx with CPUID starting with 0x26 (not according user manual)
287 1.72 2009-09-14 Martin Maurer
288 Add support for LPC13xx devices
289 1.73 2009-09-14 Martin Maurer
290 Correct again (hopefully the last time) the CPUIDs for some LPC17xx devices
291 (Now according to User Manual LPC17xx Version 00.07 (31 July 2009))
292 1.74 2009-09-14 Mario Ivancic
293 Added support for multiple HEX files, besed on internal version 1.37B.
294 NOTE: this feature is used in production in 1.37B but is not tested in this version.
295 Added numeric debug level command line switch -debugn, n=[0-5]
296 Added command line scitch -try n to specify nQuestionMarks limit. Default: 100
297 Merged in DoNotStart patch from cgommel_new
298 Static functions declarations moved from lpc21isp.h to this file
299 Modified LoadFile() to return error_code instead exit(1)
300 Removed IspEnvironment.debug_level, all code uses global debug_level
301 1.75 2010-01-05 Martin Maurer
302 Added support for LPC11xx devices (not tested at all)
303 Changed Product in LPC_DEVICE_TYPE from number to string to distinguish new LPC11 devices
304 Changed "unsigned" to "unsigned int" in LPC_DEVICE_TYPE
305 1.76 2010-02-01 Published test version without source code
306 1.77 2010-02-01 Martin Maurer
307 Corrected chip id of LPC1342 and LPC1343
308 Added a new chip type for LPC11xx and LPC13xx microcontrollers
309 Use higher area of RAM with LPC11xx and LPC13xx, because lower RAM is occupied by ISP
310 Add code to lpcprog.c to read unique id, but not yet activate.
311 Adapt block sizes for copying for each model of LPC11xx and LPC13xx
312 1.78 2010-02-16 Martin Maurer
313 Corrected chip id of LPC1751
314 Added support for LPC1759, LPC1767 and LPC1769
315 1.79 2010-02-19 Andrew Pines
316 Added __APPLE__ flag to CFLAGS in Makefile to detect and handle OS X
317 Added -Wall to Makefile to report warnings more comprehensively
318 Added #define in lpc21isp.h to substitute strnicmp with strncasecmp (needed for Unix)
319 Fixed a few format specifiers in lpcprog.c to eliminate some warnings
320 1.80 2010-03-04 Philip Munts
321 Added entries to LPCtypes[] in lpcprog.c for obsolete revisions of LPC2364/6/8/78.
322 Added entry to LPCtypes[] in lpcprog.c for new LPC2387.
323 1.81 2011-03-30 Mario Ivancic
324 As per message #517 from Thiadmer Riemersma, removed WaitForWatchDog and WatchDogSeconds
325 in PhilipsDownload().
326 1.82 2011-06-25 Moses McKnight
327 Corrected MaxCopySize for a number of the LPC11xx series
328 Added support for several more LPC11xx and LPC11Cxx series
329 1.83 2011-08-02 Martin Maurer
330 Thanks to Conurus for detecting and fixing a bug with patching checksum
331 (patching was too early, chip id was not yet available)
332 (Re-)Added code to start downloaded via "G 0 T", when using LPC1xxx
333 (Starting code at position 0 seems to work, compare to comment of version 1.70)
334 Changed some occurances of Philips to NXP
335 Added -static to Makefile (thanks to Camilo)
336 Added support for LPC1311/01 and LPC1313/01 (they have separate identifiers)
337 Correct flash size of LPC1342 to 16 KByte (thanks to Decio)
338 Abort programming when unknown NXP chip id is detected
339 1.84 2012-09-27 Philip Munts
340 Added chip id's for more LPC11xx parts, per UM10398 Rev. 11 26 July 2012
341 1.85 2012-12-13 Philip Munts
342 Fixed conditional compilation logic in lpc21isp.h to allow compiling for ARM Linux.
343 1.86 2012-12-14 diskrepairman
344 Added devices: LPC1114/203 LPC1114/303 LPC1114/323 LPC1114/333 LPC1115/303
345 1.87 2012-12-18 Philip Munts
346 Added a section of code to ResetTarget() in lpc21isp.c to allow using Linux GPIO pin
347 to control reset and ISP.
348 1.88 2013-04-25 Torsten Lang, Uwe Schneider GmbH
349 Fixed answer evaluation
350 Added sector tables for LPC1833
351 XON/XOFF handling according to LPC manual
352 Changed COMMTIMEOUTS settings according to MS help
353 Changed waiting code from tick counting to system time usage
354 Set MM timers to 1ms resolution (otherwise waiting in the serial driver is limited to multiples of 10ms)
355 Send all commands with <CR><LF> according to NXP UM
356 Change answer evaluation to match at least LPC17xx and LPC18xx families (LPC17xx just mirrors the first character of
357 the LF sequence, LPC18xx mirrors the first character and adds an <LF> which then will lead to a <CR><LF><LF>
358 sequence, all other lines are terminated with <CR><LF> as documented)
359 Change answer formatting by filtering leading <LF> characters because they can be left over from a previous response
360 Store residual data of an answer (required for the J command which will deliver two words in case of the LPC18xx)
361 Expanded configuration table by second identification word and usage flag
362 Do a two stage scan in case that a device with two identification words is detected
363 1.89 2013-06-27 Martin Maurer
364 Thanks to Manuel and Henri for bugfixes and speed-ups
365 Bugfix: In case of LPC8XX, XON/XOFF handling must be switched off,
366 otherwise download gets broken, because XON/XOFF are filtered out...
367 1.90 2013-06-27 Martin Maurer
368 Add checksum calculation for LPC8XX
369 winmm function only available in MSVC, put ifdefs around
370 Workaround for lost characters of LPC8XX
371 1.91 2013-06-28 Torsten Lang, Uwe Schneider GmbH
372 Minor bugfix for the residual data handling
373 1.92 2013-06-29 Martin Maurer
374 Thanks to Phil for reporting Linux compile errors
376 1.93 2013-07-05 Andrew Pines
377 changed Makefile to exclude "-static" from CFLAGS when building for OS X
378 changed serial timeout for *nix to use select
379 added -boothold argument to assert ISP throughtout programming sequence
380 added support for -try<n> command line argument (was in help, didn't actually work)
381 1.94 2013-08-10 Martin Maurer
382 Add (assumed) part id values for LPC4333 and LPC4337
383 Correct table entries for all LPC43xx part id numbers
384 (missing flag for two word part ids and second word for LPC4333 and LPC4353)
385 Merge in optimization (thanks to Stefan) to skip empty sectors
386 Correct help output of "-boothold"
387 Add workaround table entry for LPC4357 and word1 equal to 0x0EF60000
388 Bugfix for wrong check of word0/word1 combination
389 Correct a lot entries in lpc property table of LPC18xx and LPC43xx
390 LPC18xx and LPC43xx: Add warning message, that wipe erases only bank A
394 // Please don't use TABs in the source code !!!
396 // Don't forget to update the version string that is on the next line
397 #define VERSION_STR "1.94"
399 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
400 static char RxTmpBuf[256]; // save received data to this buffer for half-duplex
401 char * pRxTmpBuf = RxTmpBuf;
404 #if !defined COMPILE_FOR_LPC21
408 static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS);
409 static unsigned char Ascii2Hex(unsigned char c);
411 #ifdef COMPILE_FOR_WINDOWS
412 static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds);
413 static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment);
414 #endif // COMPILE_FOR_WINDOWS
416 static int AddFileHex(ISP_ENVIRONMENT *IspEnvironment, const char *arg);
417 static int AddFileBinary(ISP_ENVIRONMENT *IspEnvironment, const char *arg);
418 static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat);
420 /************* Portability layer. Serial and console I/O differences */
421 /* are taken care of here. */
423 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
424 static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
427 COMMTIMEOUTS commtimeouts;
430 /* Torsten Lang 2013-05-06 Switch to higher timer resolution (we want to use 1ms timeouts in the serial device driver!) */
431 (void)timeBeginPeriod(1UL);
434 IspEnvironment->hCom = CreateFile(IspEnvironment->serial_port, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
436 if (IspEnvironment->hCom == INVALID_HANDLE_VALUE)
438 DebugPrintf(1, "Can't open COM-Port %s ! - Error: %ld\n", IspEnvironment->serial_port, GetLastError());
442 DebugPrintf(3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
444 GetCommState(IspEnvironment->hCom, &dcb);
445 dcb.BaudRate = atol(IspEnvironment->baud_rate);
447 dcb.StopBits = ONESTOPBIT;
448 dcb.Parity = NOPARITY;
449 dcb.fDtrControl = DTR_CONTROL_DISABLE;
450 dcb.fOutX = TRUE; // TL TODO - according to LPC manual! FALSE;
451 dcb.fInX = TRUE; // TL TODO - according to LPC manual! FALSE;
453 dcb.fRtsControl = RTS_CONTROL_DISABLE;
455 // added by Herbert Demmel - iF CTS line has the wrong state, we would never send anything!
456 dcb.fOutxCtsFlow = FALSE;
457 dcb.fOutxDsrFlow = FALSE;
459 if (SetCommState(IspEnvironment->hCom, &dcb) == 0)
461 DebugPrintf(1, "Can't set baudrate %s ! - Error: %ld", IspEnvironment->baud_rate, GetLastError());
466 * Peter Hayward 02 July 2008
468 * The following call is only needed if the WaitCommEvent
469 * or possibly the GetCommMask functions are used. They are
470 * *not* in this implimentation. However, under Windows XP SP2
471 * on my laptop the use of this call causes XP to freeze (crash) while
472 * this program is running, e.g. in section 5/6/7 ... of a largish
473 * download. Removing this *unnecessary* call fixed the problem.
474 * At the same time I've added a call to SetupComm to request
475 * (not necessarity honoured) the operating system to provide
476 * large I/O buffers for high speed I/O without handshaking.
478 * SetCommMask(IspEnvironment->hCom,EV_RXCHAR | EV_TXEMPTY);
480 SetupComm(IspEnvironment->hCom, 32000, 32000);
482 SetCommMask(IspEnvironment->hCom, EV_RXCHAR | EV_TXEMPTY);
484 // Torsten Lang 2013-05-06: ReadFile may hang indefinitely with MAXDWORD/0/1/0/0 on FTDI devices!!!
485 commtimeouts.ReadIntervalTimeout = MAXDWORD;
486 commtimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
487 commtimeouts.ReadTotalTimeoutConstant = 1;
488 commtimeouts.WriteTotalTimeoutMultiplier = 0;
489 commtimeouts.WriteTotalTimeoutConstant = 0;
490 SetCommTimeouts(IspEnvironment->hCom, &commtimeouts);
492 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
494 #if defined COMPILE_FOR_LINUX
495 static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
497 IspEnvironment->fdCom = open(IspEnvironment->serial_port, O_RDWR | O_NOCTTY | O_NONBLOCK);
499 if (IspEnvironment->fdCom < 0)
502 DebugPrintf(1, "Can't open COM-Port %s ! (Error: %dd (0x%X))\n", IspEnvironment->serial_port, err, err);
506 DebugPrintf(3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
508 /* clear input & output buffers, then switch to "blocking mode" */
509 tcflush(IspEnvironment->fdCom, TCOFLUSH);
510 tcflush(IspEnvironment->fdCom, TCIFLUSH);
511 fcntl(IspEnvironment->fdCom, F_SETFL, fcntl(IspEnvironment->fdCom, F_GETFL) & ~O_NONBLOCK);
513 tcgetattr(IspEnvironment->fdCom, &IspEnvironment->oldtio); /* save current port settings */
515 bzero(&IspEnvironment->newtio, sizeof(IspEnvironment->newtio));
516 IspEnvironment->newtio.c_cflag = CS8 | CLOCAL | CREAD;
518 #if defined(__FreeBSD__) || defined(__OpenBSD__)
520 if(cfsetspeed(&IspEnvironment->newtio,(speed_t) strtol(IspEnvironment->baud_rate,NULL,10))) {
521 DebugPrintf(1, "baudrate %s not supported\n", IspEnvironment->baud_rate);
527 #define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_ispeed = IspEnvironment->newtio.c_ospeed = bps;
529 #define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_cflag |= bps;
532 switch (atol(IspEnvironment->baud_rate))
535 case 1152000: NEWTERMIOS_SETBAUDARTE(B1152000); break;
538 case 576000: NEWTERMIOS_SETBAUDARTE(B576000); break;
541 case 230400: NEWTERMIOS_SETBAUDARTE(B230400); break;
544 case 115200: NEWTERMIOS_SETBAUDARTE(B115200); break;
547 case 57600: NEWTERMIOS_SETBAUDARTE(B57600); break;
550 case 38400: NEWTERMIOS_SETBAUDARTE(B38400); break;
553 case 19200: NEWTERMIOS_SETBAUDARTE(B19200); break;
556 case 9600: NEWTERMIOS_SETBAUDARTE(B9600); break;
560 // case 32000: NEWTERMIOS_SETBAUDARTE(32000); break;
564 DebugPrintf(1, "unknown baudrate %s\n", IspEnvironment->baud_rate);
571 IspEnvironment->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF;
572 IspEnvironment->newtio.c_oflag = 0;
574 /* set input mode (non-canonical, no echo,...) */
575 IspEnvironment->newtio.c_lflag = 0;
577 cfmakeraw(&IspEnvironment->newtio);
578 IspEnvironment->newtio.c_cc[VTIME] = 1; /* inter-character timer used */
579 IspEnvironment->newtio.c_cc[VMIN] = 0; /* blocking read until 0 chars received */
581 tcflush(IspEnvironment->fdCom, TCIFLUSH);
582 if(tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio))
584 DebugPrintf(1, "Could not change serial port behaviour (wrong baudrate?)\n");
589 #endif // defined COMPILE_FOR_LINUX
591 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
592 static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
594 CloseHandle(IspEnvironment->hCom);
597 /* Torsten Lang 2013-05-06 Switch back timer resolution */
598 (void)timeEndPeriod(1UL);
602 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
604 #if defined COMPILE_FOR_LINUX
605 static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
607 tcflush(IspEnvironment->fdCom, TCOFLUSH);
608 tcflush(IspEnvironment->fdCom, TCIFLUSH);
609 tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->oldtio);
611 close(IspEnvironment->fdCom);
613 #endif // defined COMPILE_FOR_LINUX
615 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
616 void ControlXonXoffSerialPort(ISP_ENVIRONMENT *IspEnvironment, unsigned char XonXoff)
620 GetCommState(IspEnvironment->hCom, &dcb);
633 if (SetCommState(IspEnvironment->hCom, &dcb) == 0)
635 DebugPrintf(1, "Can't set XonXoff ! - Error: %ld", GetLastError());
640 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
642 #if defined COMPILE_FOR_LINUX
643 void ControlXonXoffSerialPort(ISP_ENVIRONMENT *IspEnvironment, unsigned char XonXoff)
645 if(tcgetattr(IspEnvironment->fdCom, &IspEnvironment->newtio))
647 DebugPrintf(1, "Could not get serial port behaviour\n");
653 IspEnvironment->newtio.c_iflag |= IXON;
654 IspEnvironment->newtio.c_iflag |= IXOFF;
658 IspEnvironment->newtio.c_iflag &= ~IXON;
659 IspEnvironment->newtio.c_iflag &= ~IXOFF;
662 if(tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio))
664 DebugPrintf(1, "Could not set serial port behaviour\n");
668 #endif // defined COMPILE_FOR_LINUX
670 /***************************** SendComPortBlock *************************/
671 /** Sends a block of bytes out the opened com port.
672 \param [in] s block to send.
673 \param [in] n size of the block.
675 void SendComPortBlock(ISP_ENVIRONMENT *IspEnvironment, const void *s, size_t n)
677 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
679 unsigned long realsize;
681 unsigned long rxsize;
684 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
686 DumpString(4, s, n, "Sending ");
688 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
690 if (IspEnvironment->HalfDuplex == 0)
692 WriteFile(IspEnvironment->hCom, s, n, &realsize, NULL);
698 pRxTmpBuf = RxTmpBuf;
700 // avoid buffer otherflow
701 if (n > sizeof (RxTmpBuf))
702 n = sizeof (RxTmpBuf);
704 for (m = 0; m < n; m++)
706 WriteFile(IspEnvironment->hCom, pch, 1, &realsize, NULL);
708 if ((*pch != '?') || (n != 1))
712 ReadFile(IspEnvironment->hCom, rxpch, 1, &rxsize, NULL);
713 }while (rxsize == 0);
718 *rxpch = 0; // terminate echo string
720 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
722 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
724 write(IspEnvironment->fdCom, s, n);
726 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
729 /***************************** SendComPort ******************************/
730 /** Sends a string out the opened com port.
731 \param [in] s string to send.
733 void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s)
735 SendComPortBlock(IspEnvironment, s, strlen(s));
738 /***************************** SerialTimeoutTick ************************/
739 /** Performs a timer tick. In this simple case all we do is count down
740 with protection against underflow and wrapping at the low end.
742 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
743 static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment)
745 if (IspEnvironment->serial_timeout_count <= 1)
747 IspEnvironment->serial_timeout_count = 0;
751 IspEnvironment->serial_timeout_count--;
756 /***************************** ReceiveComPortBlock **********************/
757 /** Receives a buffer from the open com port. Returns all the characters
758 ready (waits for up to 'n' milliseconds before accepting that no more
759 characters are ready) or when the buffer is full. 'n' is system dependant,
760 see SerialTimeout routines.
761 \param [out] answer buffer to hold the bytes read from the serial port.
762 \param [in] max_size the size of buffer pointed to by answer.
763 \param [out] real_size pointer to a long that returns the amout of the
764 buffer that is actually used.
766 static void ReceiveComPortBlock(ISP_ENVIRONMENT *IspEnvironment,
767 void *answer, unsigned long max_size,
768 unsigned long *real_size)
772 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
774 if (IspEnvironment->HalfDuplex == 0)
775 ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
778 *real_size = strlen (pRxTmpBuf);
781 if (max_size >= *real_size)
783 strncpy((char*) answer, pRxTmpBuf, *real_size);
785 pRxTmpBuf = RxTmpBuf;
789 strncpy((char*) answer, pRxTmpBuf, max_size);
790 *real_size = max_size;
791 pRxTmpBuf += max_size;
795 ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
798 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
800 #if defined COMPILE_FOR_LPC21
802 *real_size = read(IspEnvironment->fdCom, answer, max_size);
804 #endif // defined COMPILE_FOR_LPC21
806 #if defined COMPILE_FOR_LINUX
813 FD_ZERO(&readSet); // clear the set
814 FD_SET(IspEnvironment->fdCom,&readSet); // add this descriptor to the set
815 timeVal.tv_sec=0; // set up the timeout waiting for one to come ready (500ms)
816 timeVal.tv_usec=500*1000;
817 if(select(FD_SETSIZE,&readSet,NULL,NULL,&timeVal)==1) // wait up to 500 ms or until our data is ready
819 *real_size=read(IspEnvironment->fdCom, answer, max_size);
823 // timed out, show no characters received and timer expired
825 IspEnvironment->serial_timeout_count=0;
828 #endif // defined COMPILE_FOR_LINUX
830 sprintf(tmp_string, "Read(Length=%ld): ", (*real_size));
831 DumpString(5, answer, (*real_size), tmp_string);
833 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
836 SerialTimeoutTick(IspEnvironment);
842 /***************************** SerialTimeoutSet *************************/
843 /** Sets (or resets) the timeout to the timout period requested. Starts
844 counting to this period. This timeout support is a little odd in that the
845 timeout specifies the accumulated deadtime waiting to read not the total
846 time waiting to read. They should be close enought to the same for this
847 use. Used by the serial input routines, the actual counting takes place in
849 \param [in] timeout_milliseconds the time in milliseconds to use for
850 timeout. Note that just because it is set in milliseconds doesn't mean
851 that the granularity is that fine. In many cases (particularly Linux) it
854 static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds)
856 #if defined COMPILE_FOR_LINUX
857 IspEnvironment->serial_timeout_count = timeout_milliseconds / 100;
858 #elif defined COMPILE_FOR_LPC21
859 IspEnvironment->serial_timeout_count = timeout_milliseconds * 200;
862 IspEnvironment->serial_timeout_count = timeGetTime() + timeout_milliseconds;
864 IspEnvironment->serial_timeout_count = timeout_milliseconds;
871 /***************************** SerialTimeoutCheck ***********************/
872 /** Check to see if the serial timeout timer has run down.
873 \retval 1 if timer has run out.
874 \retval 0 if timer still has time left.
876 static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment)
878 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
880 if ((signed long)(IspEnvironment->serial_timeout_count - timeGetTime()) < 0)
885 if (IspEnvironment->serial_timeout_count == 0)
891 if (IspEnvironment->serial_timeout_count == 0)
900 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
901 /***************************** getch ************************************/
902 /** Replacement for the common dos function of the same name. Reads a
903 single unbuffered character from the 'keyboard'.
904 \return The character read from the keyboard.
910 /* Read in one character */
915 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
917 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
918 /***************************** kbhit ************************************/
919 /** Replacement for the common dos function of the same name. Indicates if
920 there are characters to be read from the console.
921 \retval 0 No characters ready.
922 \retval 1 Characters from the console ready to be read.
926 /* return 0 for no key pressed, 1 for key pressed */
927 int return_value = 0;
929 /* time struct for the select() function, to only wait a little while */
930 struct timeval select_time;
931 /* file descriptor variable for the select() call */
934 /* we're only interested in STDIN */
936 FD_SET(STDIN_FILENO, &readset);
938 /* how long to block for - this must be > 0.0, but could be changed
939 to some other setting. 10-18msec seems to work well and only
940 minimally load the system (0% CPU loading) */
941 select_time.tv_sec = 0;
942 select_time.tv_usec = 10;
944 /* is there a keystroke there? */
945 if (select(1, &readset, NULL, NULL, &select_time))
947 /* yes, remember it */
952 /* return with what we found out */
955 struct termios keyboard_origtty;
956 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
959 /***************************** PrepareKeyboardTtySettings ***************/
960 /** Set the keyboard tty to be able to check for new characters via kbhit
961 getting them via getch
964 void PrepareKeyboardTtySettings(void)
966 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
967 /* store the current tty settings */
968 if (!tcgetattr(0, &keyboard_origtty))
971 /* start with the current settings */
972 tty = keyboard_origtty;
973 /* make modifications to put it in raw mode, turn off echo */
974 tty.c_lflag &= ~ICANON;
975 tty.c_lflag &= ~ECHO;
976 tty.c_lflag &= ~ISIG;
980 /* put the settings into effect */
981 tcsetattr(0, TCSADRAIN, &tty);
987 /***************************** ResetKeyboardTtySettings *****************/
988 /** Reset the keyboard tty to original settings
990 void ResetKeyboardTtySettings(void)
992 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
993 /* reset the tty to its original settings */
994 tcsetattr(0, TCSADRAIN, &keyboard_origtty);
999 #if !defined COMPILE_FOR_LPC21
1000 /***************************** ControlModemLines ************************/
1001 /** Controls the modem lines to place the microcontroller into various
1002 states during the programming process.
1003 error rather abruptly terminates the program.
1004 \param [in] DTR the state to set the DTR line to.
1005 \param [in] RTS the state to set the RTS line to.
1007 static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS)
1009 //handle wether to invert the control lines:
1010 DTR ^= IspEnvironment->ControlLinesInverted;
1011 RTS ^= IspEnvironment->ControlLinesInverted;
1013 //handle wether to swap the control lines
1014 if (IspEnvironment->ControlLinesSwapped)
1016 unsigned char tempRTS;
1022 #if defined COMPILE_FOR_LINUX
1025 if (ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
1027 DebugPrintf(3, "ioctl get ok, status = %X\n",status);
1031 DebugPrintf(1, "ioctl get failed\n");
1034 if (DTR) status |= TIOCM_DTR;
1035 else status &= ~TIOCM_DTR;
1037 if (RTS) status |= TIOCM_RTS;
1038 else status &= ~TIOCM_RTS;
1040 if (ioctl(IspEnvironment->fdCom, TIOCMSET, &status) == 0)
1042 DebugPrintf(3, "ioctl set ok, status = %X\n",status);
1046 DebugPrintf(1, "ioctl set failed\n");
1049 if (ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
1051 DebugPrintf(3, "ioctl get ok, status = %X\n",status);
1055 DebugPrintf(1, "ioctl get failed\n");
1058 #endif // defined COMPILE_FOR_LINUX
1059 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
1061 if (DTR) EscapeCommFunction(IspEnvironment->hCom, SETDTR);
1062 else EscapeCommFunction(IspEnvironment->hCom, CLRDTR);
1064 if (RTS) EscapeCommFunction(IspEnvironment->hCom, SETRTS);
1065 else EscapeCommFunction(IspEnvironment->hCom, CLRRTS);
1067 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
1069 #if defined COMPILE_FOR_LPC21
1074 DebugPrintf(3, "DTR (%d), RTS (%d)\n", DTR, RTS);
1078 /***************************** ClearSerialPortBuffers********************/
1079 /** Empty the serial port buffers. Cleans things to a known state.
1081 void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment)
1083 #if defined COMPILE_FOR_LINUX
1084 /* variables to store the current tty state, create a new one */
1085 struct termios origtty, tty;
1087 /* store the current tty settings */
1088 tcgetattr(IspEnvironment->fdCom, &origtty);
1090 // Flush input and output buffers
1092 tcsetattr(IspEnvironment->fdCom, TCSAFLUSH, &tty);
1094 /* reset the tty to its original settings */
1095 tcsetattr(IspEnvironment->fdCom, TCSADRAIN, &origtty);
1096 #endif // defined COMPILE_FOR_LINUX
1097 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
1098 PurgeComm(IspEnvironment->hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
1099 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
1101 #endif // !defined COMPILE_FOR_LPC21
1104 #if defined COMPILE_FOR_LINUX
1105 /***************************** Sleep ************************************/
1106 /** Provide linux replacement for windows function.
1107 \param [in] Milliseconds the time to wait for in milliseconds.
1109 void Sleep(unsigned long MilliSeconds)
1111 usleep(MilliSeconds*1000); //convert to microseconds
1113 #endif // defined COMPILE_FOR_LINUX
1116 #if defined COMPILE_FOR_LPC21
1117 /** Provide linux replacement for windows function.
1118 \note I implement that one in my private header file today...
1119 \param [in] Milliseconds the time to wait for in milliseconds.
1121 /*static void Sleep(unsigned long MilliSeconds)
1123 # warning Sleep function not implemented
1126 #endif // defined COMPILE_FOR_LPC21
1130 /************* Applicationlayer. */
1132 #if !defined COMPILE_FOR_LPC21
1133 /***************************** DebugPrintf ******************************/
1134 /** Prints a debug string depending the current debug level. The higher
1135 the debug level the more detail that will be printed. Each print
1136 has an associated level, the higher the level the more detailed the
1137 debugging information being sent.
1138 \param [in] level the debug level of the print statement, if the level
1139 is less than or equal to the current debug level it will be printed.
1140 \param [in] fmt a standard printf style format string.
1141 \param [in] ... the usual printf parameters.
1143 #if !defined INTEGRATED_IN_WIN_APP
1144 void DebugPrintf(int level, const char *fmt, ...)
1148 if (level <= debug_level)
1153 vsprintf(pTemp, fmt, ap);
1160 #endif // !defined COMPILE_FOR_LPC21
1163 /***************************** ReceiveComPort ***************************/
1164 /** Receives a buffer from the open com port. Returns when the buffer is
1165 filled, the numer of requested linefeeds has been received or the timeout
1166 period has passed. The bootloaders may send 0x0d,0x0a,0x0a or 0x0d,0x0a as
1168 2013-06-28 Torsten Lang
1169 Note: We *could* filter out surplus 0x0a characters like in <CR><LF><LF>
1170 but as we don't know how the individual bootloader behaves we don't want
1171 to wait for possible surplus <LF> (which would slow down the transfer).
1172 Thus, we just terminate after the expected number of <CR><LF> sequences
1173 and leave it to the command handler in lpcprog.c to filter out surplus
1174 <LF> characters which then occur as leading character in answers or
1176 \param [in] ISPEnvironment.
1177 \param [out] Answer buffer to hold the bytes read from the serial port.
1178 \param [in] MaxSize the size of buffer pointed to by Answer.
1179 \param [out] RealSize pointer to a long that returns the amout of the
1180 buffer that is actually used.
1181 \param [in] WantedNr0x0A the maximum number of linefeeds to accept before
1183 \param [in] timeOutMilliseconds the maximum amount of time to wait before
1184 reading with an incomplete buffer.
1186 void ReceiveComPort(ISP_ENVIRONMENT *IspEnvironment,
1187 const char *Ans, unsigned long MaxSize,
1188 unsigned long *RealSize, unsigned long WantedNr0x0A,
1189 unsigned timeOutMilliseconds)
1191 unsigned long tmp_realsize;
1192 unsigned long nr_of_0x0A = 0;
1193 unsigned long nr_of_0x0D = 0;
1196 unsigned char *Answer;
1197 unsigned char *endPtr;
1198 char tmp_string[32];
1199 static char residual_data[128] = {'\0'};
1202 Answer = (unsigned char*) Ans;
1204 SerialTimeoutSet(IspEnvironment, timeOutMilliseconds);
1211 if (residual_data[0] == '\0')
1213 /* Receive new data */
1214 ReceiveComPortBlock(IspEnvironment, Answer + (*RealSize), MaxSize - 1 - (*RealSize), &tmp_realsize);
1218 /* Take over any old residual data */
1219 strcpy((char *)Answer, residual_data);
1220 tmp_realsize = strlen((char *)Answer);
1221 residual_data[0] = '\0';
1224 if (tmp_realsize != 0)
1226 for (p = (*RealSize); p < (*RealSize) + tmp_realsize; p++)
1228 /* Torsten Lang 2013-05-06 Scan for 0x0d,0x0a,0x0a and 0x0d,0x0a as linefeed pattern */
1229 if (Answer[p] == 0x0a)
1235 if (nr_of_0x0A >= WantedNr0x0A)
1237 endPtr = &Answer[p+1];
1241 else if (Answer[p] == 0x0d)
1246 else if (((signed char) Answer[p]) < 0)
1256 if (nr_of_0x0A >= WantedNr0x0A)
1258 endPtr = &Answer[p+1];
1262 (*RealSize) += tmp_realsize;
1264 } while (((*RealSize) < MaxSize) && (SerialTimeoutCheck(IspEnvironment) == 0) && (nr_of_0x0A < WantedNr0x0A) && !eof);
1266 /* Torsten Lang 2013-05-06 Store residual data and cut answer after expected nr. of 0x0a */
1267 Answer[*RealSize] = '\0';
1270 strcpy(residual_data, (char *)endPtr);
1272 /* Torsten Lang 2013-06-28 Update size info */
1273 *RealSize = endPtr-Answer;
1276 sprintf(tmp_string, "Answer(Length=%ld): ", (*RealSize));
1277 DumpString(3, Answer, (*RealSize), tmp_string);
1281 #if !defined COMPILE_FOR_LPC21
1283 /***************************** ReceiveComPortBlockComplete **************/
1284 /** Receives a fixed block from the open com port. Returns when the
1285 block is completely filled or the timeout period has passed
1286 \param [out] block buffer to hold the bytes read from the serial port.
1287 \param [in] size the size of the buffer pointed to by block.
1288 \param [in] timeOut the maximum amount of time to wait before guvung up on
1289 completing the read.
1290 \return 0 if successful, non-zero otherwise.
1292 int ReceiveComPortBlockComplete(ISP_ENVIRONMENT *IspEnvironment,
1293 void *block, size_t size, unsigned timeout)
1295 unsigned long realsize = 0, read;
1297 char tmp_string[32];
1299 result = (char*) block;
1301 SerialTimeoutSet(IspEnvironment, timeout);
1305 ReceiveComPortBlock(IspEnvironment, result + realsize, size - realsize, &read);
1309 } while ((realsize < size) && (SerialTimeoutCheck(IspEnvironment) == 0));
1311 sprintf(tmp_string, "Answer(Length=%ld): ", realsize);
1312 DumpString(3, result, realsize, tmp_string);
1314 if (realsize != size)
1321 /***************************** ReadArguments ****************************/
1322 /** Reads the command line arguments and parses it for the various
1323 options. Uses the same arguments as main. Used to separate the command
1324 line parsing from main and improve its readability. This should also make
1325 it easier to modify the command line parsing in the future.
1326 \param [in] argc the number of arguments.
1327 \param [in] argv an array of pointers to the arguments.
1329 static void ReadArguments(ISP_ENVIRONMENT *IspEnvironment, unsigned int argc, char *argv[])
1335 for (i = 1; i < argc - 3; i++)
1337 if (stricmp(argv[i], "-wipe") == 0)
1339 IspEnvironment->WipeDevice = 1;
1340 DebugPrintf(3, "Wipe entire device before writing.\n");
1344 if (stricmp(argv[i], "-bin") == 0)
1346 IspEnvironment->FileFormat = FORMAT_BINARY;
1347 DebugPrintf(3, "Binary format file input.\n");
1351 if (stricmp(argv[i], "-hex") == 0)
1353 IspEnvironment->FileFormat = FORMAT_HEX;
1354 DebugPrintf(3, "Hex format file input.\n");
1358 if (stricmp(argv[i], "-logfile") == 0)
1360 IspEnvironment->LogFile = 1;
1361 DebugPrintf(3, "Log terminal output.\n");
1365 if (stricmp(argv[i], "-detectonly") == 0)
1367 IspEnvironment->DetectOnly = 1;
1368 IspEnvironment->ProgramChip = 0;
1369 DebugPrintf(3, "Only detect LPC chip part id.\n");
1373 if(strnicmp(argv[i],"-debug", 6) == 0)
1377 while(*num && isdigit(*num) == 0) num++;
1378 if(isdigit(*num) != 0) debug_level = atoi( num);
1379 else debug_level = 4;
1380 DebugPrintf(3, "Turn on debug, level: %d.\n", debug_level);
1384 if (stricmp(argv[i], "-boothold") == 0)
1386 IspEnvironment->BootHold = 1;
1387 DebugPrintf(3, "hold EnableBootLoader asserted throughout programming sequence.\n");
1391 if (stricmp(argv[i], "-donotstart") == 0)
1393 IspEnvironment->DoNotStart = 1;
1394 DebugPrintf(3, "Do NOT start MCU after programming.\n");
1398 if(strnicmp(argv[i],"-try", 4) == 0)
1402 retry=atoi(&argv[i][4]);
1405 IspEnvironment->nQuestionMarks=retry;
1406 DebugPrintf(3, "Retry count: %d.\n", IspEnvironment->nQuestionMarks);
1410 fprintf(stderr,"invalid argument for -try: \"%s\"\n",argv[i]);
1416 if (stricmp(argv[i], "-control") == 0)
1418 IspEnvironment->ControlLines = 1;
1419 DebugPrintf(3, "Use RTS/DTR to control target state.\n");
1423 if (stricmp(argv[i], "-controlswap") == 0)
1425 IspEnvironment->ControlLinesSwapped = 1;
1426 DebugPrintf(3, "Use RTS to control reset, and DTR to control P0.14(ISP).\n");
1430 if (stricmp(argv[i], "-controlinv") == 0)
1432 IspEnvironment->ControlLinesInverted = 1;
1433 DebugPrintf(3, "Invert state of RTS & DTR (0=true/assert/set, 1=false/deassert/clear).\n");
1437 if (stricmp(argv[i], "-halfduplex") == 0)
1439 IspEnvironment->HalfDuplex = 1;
1440 DebugPrintf(3, "halfduplex serial communication.\n");
1444 if (stricmp(argv[i], "-ADARM") == 0)
1446 IspEnvironment->micro = ANALOG_DEVICES_ARM;
1447 DebugPrintf(2, "Target: Analog Devices.\n");
1451 if (stricmp(argv[i], "-NXPARM") == 0 || stricmp(argv[i], "-PHILIPSARM") == 0)
1453 IspEnvironment->micro = NXP_ARM;
1454 DebugPrintf(2, "Target: NXP.\n");
1458 if (stricmp(argv[i], "-Verify") == 0)
1460 IspEnvironment->Verify = 1;
1461 DebugPrintf(2, "Verify after copy RAM to Flash.\n");
1465 #ifdef INTEGRATED_IN_WIN_APP
1466 if (stricmp(argv[i], "-nosync") == 0)
1468 IspEnvironment->NoSync = 1;
1469 DebugPrintf(2, "Performing no syncing, already done.\n");
1474 #ifdef TERMINAL_SUPPORT
1475 if (CheckTerminalParameters(IspEnvironment, argv[i]))
1481 if(*argv[i] == '-') DebugPrintf( 2, "Unknown command line option: \"%s\"\n", argv[i]);
1485 if(IspEnvironment->FileFormat == FORMAT_HEX)
1487 ret_val = AddFileHex(IspEnvironment, argv[i]);
1491 ret_val = AddFileBinary(IspEnvironment, argv[i]);
1495 DebugPrintf( 2, "Unknown command line option: \"%s\"\n", argv[i]);
1500 // Newest cygwin delivers a '\x0d' at the end of argument
1501 // when calling lpc21isp from batch file
1502 for (i = 0; i < strlen(argv[argc - 1]) && i < (sizeof(IspEnvironment->StringOscillator) - 1) &&
1503 argv[argc - 1][i] >= '0' && argv[argc - 1][i] <= '9'; i++)
1505 IspEnvironment->StringOscillator[i] = argv[argc - 1][i];
1507 IspEnvironment->StringOscillator[i] = 0;
1509 IspEnvironment->serial_port = argv[argc - 3];
1510 IspEnvironment->baud_rate = argv[argc - 2];
1515 debug_level = (debug_level < 2) ? 2 : debug_level;
1521 "Portable command line ISP\n"
1522 "for NXP LPC family and Analog Devices ADUC 70xx\n"
1523 "Version " VERSION_STR " compiled for " COMPILED_FOR ": " __DATE__ ", " __TIME__ "\n"
1524 "Copyright (c) by Martin Maurer, 2003-2013, Email: Martin.Maurer@clibb.de\n"
1525 "Portions Copyright (c) by Aeolus Development 2004, www.aeolusdevelopment.com\n"
1528 DebugPrintf(1, "Syntax: lpc21isp [Options] file[ file[ ...]] comport baudrate Oscillator_in_kHz\n\n"
1529 "Example: lpc21isp test.hex com1 115200 14746\n\n"
1530 "Options: -bin for uploading binary file\n"
1531 " -hex for uploading file in intel hex format (default)\n"
1532 " -term for starting terminal after upload\n"
1533 " -termonly for starting terminal without an upload\n"
1534 " -localecho for local echo in terminal\n"
1535 " -detectonly detect only used LPC chiptype (NXPARM only)\n"
1536 " -debug0 for no debug\n"
1537 " -debug3 for progress info only\n"
1538 " -debug5 for full debug\n"
1539 " -donotstart do not start MCU after download\n"
1540 " -try<n> try n times to synchronise\n"
1541 " -wipe Erase entire device before upload\n"
1542 " -control for controlling RS232 lines for easier booting\n"
1543 " (Reset = DTR, EnableBootLoader = RTS)\n"
1544 " -boothold hold EnableBootLoader asserted throughout sequence\n"
1545 #ifdef INTEGRATED_IN_WIN_APP
1546 " -nosync Do not synchronize device via '?'\n"
1548 " -controlswap swap RS232 control lines\n"
1549 " (Reset = RTS, EnableBootLoader = DTR)\n"
1550 " -controlinv Invert state of RTS & DTR \n"
1551 " (0=true/assert/set, 1=false/deassert/clear).\n"
1552 " -verify Verify the data in Flash after every writes to\n"
1553 " sector. To detect errors in writing to Flash ROM\n"
1554 " -logfile for enabling logging of terminal output to lpc21isp.log\n"
1555 " -halfduplex use halfduplex serial communication (i.e. with K-Line)\n"
1556 " -ADARM for downloading to an Analog Devices\n"
1557 " ARM microcontroller ADUC70xx\n"
1558 " -NXPARM for downloading to a chip of NXP LPC family (default)\n");
1563 if (IspEnvironment->micro == NXP_ARM)
1565 // If StringOscillator is bigger than 100 MHz, there seems to be something wrong
1566 if (strlen(IspEnvironment->StringOscillator) > 5)
1568 DebugPrintf(1, "Invalid crystal frequency %s\n", IspEnvironment->StringOscillator);
1574 /***************************** ResetTarget ******************************/
1575 /** Resets the target leaving it in either download (program) mode or
1577 \param [in] mode the mode to leave the target in.
1579 void ResetTarget(ISP_ENVIRONMENT *IspEnvironment, TARGET_MODE mode)
1581 #if defined(__linux__) && defined(GPIO_RST) && defined(GPIO_ISP)
1583 // This code section allows using Linux GPIO pins to control the -RST and -ISP
1584 // signals of the target microcontroller.
1586 // Build lpc21isp to use Linux GPIO like this:
1588 // make CFLAGS="-Wall -DGPIO_ISP=23 -DGPIO_RST=18"
1590 // The GPIO pins must be pre-configured in /etc/rc.local (or other startup script)
1591 // similar to the following:
1593 // # Configure -ISP signal
1594 // echo 23 >/sys/class/gpio/export
1595 // echo out >/sys/class/gpio/gpio23/direction
1596 // echo 1 >/sys/class/gpio/gpio23/value
1597 // chown root.gpio /sys/class/gpio/gpio23/value
1598 // chmod 660 /sys/class/gpio/gpio23/value
1600 // # Configure -RST signal
1601 // echo 18 >/sys/class/gpio/export
1602 // echo out >/sys/class/gpio/gpio18/direction
1603 // echo 1 >/sys/class/gpio/gpio18/value
1604 // chown root.gpio /sys/class/gpio/gpio18/value
1605 // chmod 660 /sys/class/gpio/gpio18/value
1607 // Then if the user is a member of the gpio group, lpc21isp will not requre any
1608 // special permissions to access the GPIO signals.
1610 char gpio_isp_filename[256];
1611 char gpio_rst_filename[256];
1615 memset(gpio_isp_filename, 0, sizeof(gpio_isp_filename));
1616 sprintf(gpio_isp_filename, "/sys/class/gpio/gpio%d/value", GPIO_ISP);
1618 memset(gpio_rst_filename, 0, sizeof(gpio_rst_filename));
1619 sprintf(gpio_rst_filename, "/sys/class/gpio/gpio%d/value", GPIO_RST);
1621 gpio_isp = open(gpio_isp_filename, O_WRONLY);
1624 fprintf(stderr, "ERROR: open() for %s failed, %s\n", gpio_isp_filename, strerror(errno));
1628 gpio_rst = open(gpio_rst_filename, O_WRONLY);
1631 fprintf(stderr, "ERROR: open() for %s failed, %s\n", gpio_rst_filename, strerror(errno));
1638 write(gpio_isp, "0\n", 2); // Assert -ISP
1640 write(gpio_rst, "0\n", 2); // Assert -RST
1642 write(gpio_rst, "1\n", 2); // Deassert -RST
1644 write(gpio_isp, "1\n", 2); // Deassert -ISP
1649 write(gpio_rst, "0\n", 2); // Assert -RST
1651 write(gpio_rst, "1\n", 2); // Deassert -ISP
1662 if (IspEnvironment->ControlLines)
1666 /* Reset and jump to boot loader. */
1668 ControlModemLines(IspEnvironment, 1, 1);
1670 ClearSerialPortBuffers(IspEnvironment);
1672 ControlModemLines(IspEnvironment, 0, 1);
1673 //Longer delay is the Reset signal is conected to an external rest controller
1675 // Clear the RTS line after having reset the micro
1676 // Needed for the "GO <Address> <Mode>" ISP command to work */
1677 if(!IspEnvironment->BootHold)
1679 ControlModemLines(IspEnvironment, 0, 0);
1683 /* Reset and start uploaded program */
1685 ControlModemLines(IspEnvironment, 1, 0);
1687 ClearSerialPortBuffers(IspEnvironment);
1689 ControlModemLines(IspEnvironment, 0, 0);
1697 /***************************** Ascii2Hex ********************************/
1698 /** Converts a hex character to its equivalent number value. In case of an
1699 error rather abruptly terminates the program.
1700 \param [in] c the hex digit to convert.
1701 \return the value of the hex digit.
1703 static unsigned char Ascii2Hex(unsigned char c)
1705 if (c >= '0' && c <= '9')
1707 return (unsigned char)(c - '0');
1710 if (c >= 'A' && c <= 'F')
1712 return (unsigned char)(c - 'A' + 10);
1715 if (c >= 'a' && c <= 'f')
1717 return (unsigned char)(c - 'a' + 10);
1720 DebugPrintf(1, "Wrong Hex-Nibble %c (%02X)\n", c, c);
1723 return 0; // this "return" will never be reached, but some compilers give a warning if it is not present
1727 /***************************** AddFileHex *******************************/
1728 /** Add a file to the list of files to read in, flag it as hex format.
1729 \param [in] IspEnvironment Programming environment.
1730 \param [in] arg The argument that was passed to the program as a file name.
1731 \return 0 on success, an error code otherwise.
1733 static int AddFileHex(ISP_ENVIRONMENT *IspEnvironment, const char *arg)
1737 // Add file to list. If cannot allocate storage for node return an error.
1738 entry = malloc(sizeof(FILE_LIST));
1741 DebugPrintf(1, "Error %d Could not allocated memory for file node %s\n", ERR_ALLOC_FILE_LIST, arg);
1742 return ERR_ALLOC_FILE_LIST;
1745 // Build up entry and insert it at the start of the list.
1747 entry->prev = IspEnvironment->f_list;
1748 entry->hex_flag = 1;
1749 IspEnvironment->f_list = entry;
1751 return 0; // Success.
1755 /***************************** AddFileBinary ****************************/
1756 /** Add a file to the list of files to read in, flag it as binary format.
1757 \param [in] IspEnvironment Programming environment.
1758 \param [in] arg The argument that was passed to the program as a file name.
1759 \return 0 on success, an error code otherwise.
1761 static int AddFileBinary(ISP_ENVIRONMENT *IspEnvironment, const char *arg)
1765 // Add file to list. If cannot allocate storage for node return an error.
1766 entry = malloc(sizeof(FILE_LIST));
1769 DebugPrintf( 1, "Error %d Could not allocated memory for file node %s\n", ERR_ALLOC_FILE_LIST, arg);
1770 return ERR_ALLOC_FILE_LIST;
1773 // Build up entry and insert it at the start of the list.
1775 entry->prev = IspEnvironment->f_list;
1776 entry->hex_flag = 0;
1777 IspEnvironment->f_list = entry;
1779 return 0; // Success.
1783 void ReadHexFile(ISP_ENVIRONMENT *IspEnvironment)
1785 LoadFile(IspEnvironment);
1787 if (IspEnvironment->BinaryLength)
1789 BINARY* FileContent = IspEnvironment->FileContent;
1792 unsigned char RecordLength;
1793 unsigned short RecordAddress;
1794 unsigned long RealAddress = 0;
1795 unsigned char RecordType;
1796 unsigned char Hexvalue;
1797 unsigned long StartAddress;
1798 int BinaryOffsetDefined = 0;
1802 DebugPrintf(3, "Converting file %s to binary format...\n", IspEnvironment->input_file);
1805 while (Pos < IspEnvironment->BinaryLength)
1807 if (FileContent[Pos] == '\r')
1813 if (FileContent[Pos] == '\n')
1819 if (FileContent[Pos] != ':')
1821 DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
1827 RecordLength = Ascii2Hex(FileContent[Pos++]);
1829 RecordLength |= Ascii2Hex(FileContent[Pos++]);
1831 DebugPrintf(4, "RecordLength = %02X\n", RecordLength);
1833 RecordAddress = Ascii2Hex(FileContent[Pos++]);
1834 RecordAddress <<= 4;
1835 RecordAddress |= Ascii2Hex(FileContent[Pos++]);
1836 RecordAddress <<= 4;
1837 RecordAddress |= Ascii2Hex(FileContent[Pos++]);
1838 RecordAddress <<= 4;
1839 RecordAddress |= Ascii2Hex(FileContent[Pos++]);
1841 DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);
1843 RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;
1845 DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);
1847 RecordType = Ascii2Hex(FileContent[Pos++]);
1849 RecordType |= Ascii2Hex(FileContent[Pos++]);
1851 DebugPrintf(4, "RecordType = %02X\n", RecordType);
1853 if (RecordType == 0x00) // 00 - Data record
1856 * Binary Offset is defined as soon as first data record read
1859 //BinaryOffsetDefined = 1;
1861 // Memory for binary file big enough ?
1862 while ((RealAddress + RecordLength - IspEnvironment->BinaryOffset) > IspEnvironment->BinaryMemSize)
1864 IspEnvironment->BinaryMemSize <<= 1; // Double the size allocated !!!
1865 IspEnvironment->BinaryContent = (BINARY*) realloc(IspEnvironment->BinaryContent, IspEnvironment->BinaryMemSize);
1868 // We need to know, what the highest address is,
1869 // how many bytes / sectors we must flash
1870 if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
1872 IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
1873 DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
1876 for (i = 0; i < RecordLength; i++)
1878 Hexvalue = Ascii2Hex(FileContent[Pos++]);
1880 Hexvalue |= Ascii2Hex(FileContent[Pos++]);
1881 IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
1884 else if (RecordType == 0x01) // 01 - End of file record
1888 else if (RecordType == 0x02) // 02 - Extended segment address record
1890 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
1895 RealAddress = Ascii2Hex(FileContent[Pos++]);
1899 RealAddress |= Ascii2Hex(FileContent[Pos++]);
1904 else if (RecordType == 0x03) // 03 - Start segment address record
1906 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
1911 RealAddress = Ascii2Hex(FileContent[Pos++]);
1915 RealAddress |= Ascii2Hex(FileContent[Pos++]);
1920 else if (RecordType == 0x04) // 04 - Extended linear address record, used by IAR
1922 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
1927 RealAddress = Ascii2Hex(FileContent[Pos++]);
1931 RealAddress |= Ascii2Hex(FileContent[Pos++]);
1935 if (!BinaryOffsetDefined)
1937 // set startaddress of BinaryContent
1938 // use of LPC_FLASHMASK to allow a memory range, not taking the first
1939 // [04] record as actual start-address.
1940 IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
1944 if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
1946 DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n"
1947 "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
1948 IspEnvironment->BinaryOffset, RealAddress);
1953 else if (RecordType == 0x05) // 05 - Start linear address record
1956 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
1961 StartAddress = Ascii2Hex(FileContent[Pos++]);
1965 StartAddress |= Ascii2Hex(FileContent[Pos++]);
1968 DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
1969 IspEnvironment->StartAddress = StartAddress;
1972 while (FileContent[Pos++] != 0x0a) // Search till line end
1977 DebugPrintf(2, "\tconverted to binary format...\n");
1979 // When debugging is switched on, output result of conversion to file debugout.bin
1980 if (debug_level >= 4)
1983 fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
1984 write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
1992 /***************************** LoadFile *********************************/
1993 /** Loads the requested file to download into memory.
1994 \param [in] IspEnvironment structure containing input filename
1995 \param [in] filename the name of the file to read in.
1996 \param [in] FileFormat the format of the file to read in (FORMAT_HEX or FORMAT_BINARY)
1997 \return 0 if successful, otherwise an error code.
1999 static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat)
2003 int BinaryOffsetDefined;
2005 unsigned long FileLength;
2006 BINARY *FileContent; /**< Used to store the content of a hex */
2007 /* file before converting to binary. */
2008 unsigned long BinaryMemSize;
2010 fd = open(filename, O_RDONLY | O_BINARY);
2013 DebugPrintf(1, "Can't open file %s\n", filename);
2014 return ERR_FILE_OPEN_HEX;
2017 FileLength = lseek(fd, 0L, 2); // Get file size
2019 if (FileLength == (size_t)-1)
2021 DebugPrintf(1, "\nFileLength = -1 !?!\n");
2022 return ERR_FILE_SIZE_HEX;
2027 // Just read the entire file into memory to parse.
2028 FileContent = (BINARY*) malloc(FileLength);
2030 if( FileContent == 0)
2032 DebugPrintf( 1, "\nCouldn't allocate enough memory for file.\n");
2033 return ERR_FILE_ALLOC_HEX;
2036 BinaryOffsetDefined = 0;
2038 BinaryMemSize = IspEnvironment->BinaryLength;
2040 read(fd, FileContent, FileLength);
2044 DebugPrintf(2, "File %s:\n\tloaded...\n", filename);
2046 // Intel-Hex -> Binary Conversion
2048 if (FileFormat == FORMAT_HEX)
2050 unsigned char RecordLength;
2051 unsigned short RecordAddress;
2052 unsigned long RealAddress = 0;
2053 unsigned char RecordType;
2054 unsigned char Hexvalue;
2055 unsigned long StartAddress;
2057 DebugPrintf(3, "Converting file %s to binary format...\n", filename);
2060 while (Pos < FileLength)
2062 if (FileContent[Pos] == '\r')
2068 if (FileContent[Pos] == '\n')
2074 if (FileContent[Pos] != ':')
2076 DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
2082 RecordLength = Ascii2Hex(FileContent[Pos++]);
2084 RecordLength |= Ascii2Hex(FileContent[Pos++]);
2086 DebugPrintf(4, "RecordLength = %02X\n", RecordLength);
2088 RecordAddress = Ascii2Hex(FileContent[Pos++]);
2089 RecordAddress <<= 4;
2090 RecordAddress |= Ascii2Hex(FileContent[Pos++]);
2091 RecordAddress <<= 4;
2092 RecordAddress |= Ascii2Hex(FileContent[Pos++]);
2093 RecordAddress <<= 4;
2094 RecordAddress |= Ascii2Hex(FileContent[Pos++]);
2096 DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);
2098 RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;
2100 DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);
2102 RecordType = Ascii2Hex(FileContent[Pos++]);
2104 RecordType |= Ascii2Hex(FileContent[Pos++]);
2106 DebugPrintf(4, "RecordType = %02X\n", RecordType);
2108 if (RecordType == 0x00) // 00 - Data record
2111 * Binary Offset is defined as soon as first data record read
2113 BinaryOffsetDefined = 1;
2114 // Memory for binary file big enough ?
2115 while (RealAddress + RecordLength - IspEnvironment->BinaryOffset > BinaryMemSize)
2117 if(!BinaryMemSize) BinaryMemSize = FileLength * 2;
2118 else BinaryMemSize <<= 1;
2119 IspEnvironment->BinaryContent = realloc(IspEnvironment->BinaryContent, BinaryMemSize);
2122 // We need to know, what the highest address is,
2123 // how many bytes / sectors we must flash
2124 if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
2126 IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
2127 DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
2130 for (i = 0; i < RecordLength; i++)
2132 Hexvalue = Ascii2Hex(FileContent[Pos++]);
2134 Hexvalue |= Ascii2Hex(FileContent[Pos++]);
2135 IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
2138 else if (RecordType == 0x01) // 01 - End of file record
2142 else if (RecordType == 0x02) // 02 - Extended segment address record
2144 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
2149 RealAddress = Ascii2Hex(FileContent[Pos++]);
2153 RealAddress |= Ascii2Hex(FileContent[Pos++]);
2158 else if (RecordType == 0x03) // 03 - Start segment address record
2160 unsigned long cs,ip;
2162 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
2167 StartAddress = Ascii2Hex(FileContent[Pos++]);
2171 StartAddress |= Ascii2Hex(FileContent[Pos++]);
2174 cs = StartAddress >> 16; //high part
2175 ip = StartAddress & 0xffff; //low part
2176 StartAddress = cs*16+ip; //segmented 20-bit space
2177 DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
2178 IspEnvironment->StartAddress = StartAddress;
2180 else if (RecordType == 0x04) // 04 - Extended linear address record, used by IAR
2182 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
2187 RealAddress = Ascii2Hex(FileContent[Pos++]);
2191 RealAddress |= Ascii2Hex(FileContent[Pos++]);
2195 if (!BinaryOffsetDefined)
2197 // set startaddress of BinaryContent
2198 // use of LPC_FLASHMASK to allow a memory range, not taking the first
2199 // [04] record as actual start-address.
2200 IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
2204 if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
2206 DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n");
2207 DebugPrintf(1, "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
2208 IspEnvironment->BinaryOffset, RealAddress);
2209 return ERR_MEMORY_RANGE;
2213 else if (RecordType == 0x05) // 05 - Start linear address record
2216 for (i = 0; i < RecordLength * 2; i++) // double amount of nibbles
2221 StartAddress = Ascii2Hex(FileContent[Pos++]);
2225 StartAddress |= Ascii2Hex(FileContent[Pos++]);
2228 DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
2229 IspEnvironment->StartAddress = StartAddress;
2234 DebugPrintf( 1, "Error %d RecordType %02X not yet implemented\n", ERR_RECORD_TYPE_LOADFILE, RecordType);
2235 return( ERR_RECORD_TYPE_LOADFILE);
2238 while (FileContent[Pos++] != 0x0a) // Search till line end
2243 DebugPrintf(2, "\tconverted to binary format...\n");
2245 // When debugging is switched on, output result of conversion to file debugout.bin
2246 if (debug_level >= 4)
2249 fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
2250 write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
2254 free( FileContent); // Done with file contents
2256 else // FORMAT_BINARY
2258 IspEnvironment->BinaryContent = FileContent;
2259 IspEnvironment->BinaryLength = FileLength;
2262 DebugPrintf(2, "\timage size : %ld\n", IspEnvironment->BinaryLength);
2267 /***************************** LoadFiles1 ********************************/
2268 /** Loads the requested files to download into memory.
2269 \param [in] IspEnvironment structure containing input filename(s).
2270 \param [in] file simple linked list of files to read
2271 \return 0 if successful, otherwise an error code.
2273 static int LoadFiles1(ISP_ENVIRONMENT *IspEnvironment, const FILE_LIST *file)
2277 if( file->prev != 0)
2279 DebugPrintf( 3, "Follow file list %s\n", file->name);
2281 ret_val = LoadFiles1( IspEnvironment, file->prev);
2288 DebugPrintf( 3, "Attempt to read File %s\n", file->name);
2289 if(file->hex_flag != 0)
2291 ret_val = LoadFile(IspEnvironment, file->name, FORMAT_HEX);
2295 ret_val = LoadFile(IspEnvironment, file->name, FORMAT_BINARY);
2305 /***************************** LoadFiles ********************************/
2306 /** Loads the requested files to download into memory.
2307 \param [in] IspEnvironment structure containing input filename(s).
2308 \param [in] file simple linked list of files to read
2309 \return 0 if successful, otherwise an error code.
2311 static int LoadFiles(ISP_ENVIRONMENT *IspEnvironment)
2315 ret_val = LoadFiles1(IspEnvironment, IspEnvironment->f_list);
2318 exit(1); // return ret_val;
2321 DebugPrintf( 2, "Image size : %ld\n", IspEnvironment->BinaryLength);
2323 // check length to flash for correct alignment, can happen with broken ld-scripts
2324 if (IspEnvironment->BinaryLength % 4 != 0)
2326 unsigned long NewBinaryLength = ((IspEnvironment->BinaryLength + 3)/4) * 4;
2328 DebugPrintf( 2, "Warning: data not aligned to 32 bits, padded (length was %lX, now %lX)\n", IspEnvironment->BinaryLength, NewBinaryLength);
2330 IspEnvironment->BinaryLength = NewBinaryLength;
2333 // When debugging is switched on, output result of conversion to file debugout.bin
2334 if(debug_level >= 4)
2337 DebugPrintf( 1, "Dumping image file.\n");
2338 fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
2339 write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
2344 #endif // !defined COMPILE_FOR_LPC21
2346 #ifndef COMPILE_FOR_LPC21
2347 int PerformActions(ISP_ENVIRONMENT *IspEnvironment)
2349 int downloadResult = -1;
2351 DebugPrintf(2, "lpc21isp version " VERSION_STR "\n");
2353 /* Download requested, read in the input file. */
2354 if (IspEnvironment->ProgramChip)
2356 LoadFiles(IspEnvironment);
2359 OpenSerialPort(IspEnvironment); /* Open the serial port to the microcontroller. */
2361 ResetTarget(IspEnvironment, PROGRAM_MODE);
2363 ClearSerialPortBuffers(IspEnvironment);
2365 /* Perform the requested download. */
2366 if (IspEnvironment->ProgramChip || IspEnvironment->DetectOnly)
2368 switch (IspEnvironment->micro)
2372 downloadResult = NxpDownload(IspEnvironment);
2377 case ANALOG_DEVICES_ARM:
2378 downloadResult = AnalogDevicesDownload(IspEnvironment);
2383 if (downloadResult != 0)
2385 CloseSerialPort(IspEnvironment);
2386 exit(downloadResult);
2390 if (IspEnvironment->StartAddress == 0 || IspEnvironment->TerminalOnly)
2392 /* Only reset target if startaddress = 0
2393 * Otherwise stay with the running program as started in Download()
2395 ResetTarget(IspEnvironment, RUN_MODE);
2398 debug_level = 1; /* From now on there is no more debug output !! */
2399 /* Therefore switch it off... */
2401 #ifdef TERMINAL_SUPPORT
2402 // Pass control to Terminal which will provide a terminal if one was asked for
2403 // User asked for terminal emulation, provide a really dumb terminal.
2404 Terminal(IspEnvironment);
2407 CloseSerialPort(IspEnvironment); /* All done, close the serial port to the */
2413 /***************************** main *************************************/
2414 /** main. Everything starts from here.
2415 \param [in] argc the number of arguments.
2416 \param [in] argv an array of pointers to the arguments.
2419 #if !defined COMPILE_FOR_LPC21
2421 #if defined INTEGRATED_IN_WIN_APP
2422 int AppDoProgram(int argc, char *argv[])
2424 int main(int argc, char *argv[])
2427 ISP_ENVIRONMENT IspEnvironment;
2429 // Initialize debug level
2432 // Initialize ISP Environment
2433 memset(&IspEnvironment, 0, sizeof(IspEnvironment)); // Clear the IspEnviroment to a known value
2434 IspEnvironment.micro = NXP_ARM; // Default Micro
2435 IspEnvironment.FileFormat = FORMAT_HEX; // Default File Format
2436 IspEnvironment.ProgramChip = TRUE; // Default to Programming the chip
2437 IspEnvironment.nQuestionMarks = 100;
2438 IspEnvironment.DoNotStart = 0;
2439 IspEnvironment.BootHold = 0;
2440 ReadArguments(&IspEnvironment, argc, argv); // Read and parse the command line
2442 return PerformActions(&IspEnvironment); // Do as requested !
2445 #endif // !defined COMPILE_FOR_LPC21
2447 /***************************** DumpString ******************************/
2448 /** Prints an area of memory to stdout. Converts non-printables to hex.
2449 \param [in] level the debug level of the block to be dumped. If this is
2450 less than or equal to the current debug level than the dump will happen
2451 otherwise this just returns.
2452 \param [in] b pointer to an area of memory.
2453 \param [in] size the length of the memory block to print.
2454 \param [in] prefix string is a pointer to a prefix string.
2456 void DumpString(int level, const void *b, size_t size, const char *prefix_string)
2459 const char * s = (const char*) b;
2462 DebugPrintf(level, prefix_string);
2464 DebugPrintf(level, "'");
2465 for (i = 0; i < size; i++)
2468 if (c >= 0x20 && c <= 0x7e) /*isprint?*/
2470 DebugPrintf(level, "%c", c);
2474 DebugPrintf(level, "(%02X)", c);
2477 DebugPrintf(level, "'\n");