root/trunk/tools/lpc21isp/lpc21isp.c

Revision 566, 71.4 KB (checked in by goodea, 4 months ago)

Update lpc21isp

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