root/trunk/tools/lpc21isp/lpc21isp.c

Revision 306, 97.7 kB (checked in by goodea, 2 years ago)

isp

Line 
1 /******************************************************************************
2
3 Project:           Portable command line ISP for Philips LPC2000 family
4                    and Analog Devices ADUC70xx
5
6 Filename:          lpc21isp.c
7
8 Compiler:          Microsoft VC 6/7, GCC Cygwin, GCC Linux
9
10 Autor:             Martin Maurer (Martin.Maurer@clibb.de)
11
12 Copyright:         (c) Martin Maurer 2003-2007, All rights reserved
13 Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com
14
15 Version:           1.39
16
17 Change-History:
18
19  1.00  2004-01-08  Initial Version, tested for MSVC6/7 and GCC under Cygwin
20  1.01  2004-01-10  Porting to Linux (at least compiling must work)
21  1.02  2004-01-10  Implemented conversion intel hex format -> binary
22  1.03  2004-01-25  Preparation to upload to public website
23  1.04  2004-02-12  Merged in bugfixes by Soeren Gust
24  1.05  2004-03-14  Implement printing of error codes as text / strings
25  1.06  2004-03-09  Merged in bugfixes by Charles Manning:
26                    The '?' sychronisation does not reliably respond to the first '?'.
27                    I added some retries.
28                    The LPC2106 sometimes responds to the '?' by echoing them back.
29                    This sometimes causes an attempt to match "?Synchonized".
30                    Added code to strip off any leading '?'s.
31                    Timeouts were too long.
32                    Change from RTS/CTS to no flow control.
33                    Done because many/most people will use only 3-wire comms.
34                    Added some progress tracing.
35  1.07  2004-03-14  Implement handling of control lines for easier booting
36  1.08  2004-04-01  Bugfix for upload problem
37  1.09  2004-04-03  Redesign of upload routine
38                    Now always 180 byte blocks are uploaded, to prevent
39                    small junks in uuencoding
40  1.10  2004-04-03  Clear buffers before sending commands to LPC21xx,
41                    this prevents synchronizing errors when previously loaded
42                    program does a lot of output, so FIFO of PC runs full
43  1.11  2004-04-03  Small optimization for controlling reset line
44                    otherwise termonly starts LPC twice, free PC buffers
45  1.12  2004-04-04  Add switch to enable logging terminal output to lpc21isp.log
46  1.13  2004-05-19  Merged in improvement by Charles Manning:
47                    Instead of exiting the wrong hex file size is corrected
48  1.14  2004-07-07  Merged in improvement by Alex Holden:
49                    Remove little/big endian dependancy
50  1.15  2004-09-27  Temporary improvement by Cyril Holweck:
51                    Removed test (data echoed = data transmited) on the main
52                    data transfert, since this was the biggest failure
53                    reason and is covered by checksome anyway.
54                    Added COMPILE_FOR_LPC21, to have target dump it's own
55                    memory to stdout.
56  1.16  2004-10-09  Merged in bugfix / improvement by Sinelnikov Evgeny
57                    I found out that Linux and Windows serial port initialization
58                    are different with pinouts states. My board don't get
59                    reset signal at first cycle of DTR pinout moving.
60                    And I add this moving to initalization cycle.
61  1.17  2004-10-21  Changes by Cyril Holweck
62                    Divide main, take out the real programming function, that can
63                    also be used by a target to copy its own code to another.
64  1.18  2004-10-26  Changes by Cyril Holweck
65                    Added a "G 0 A\r\n" at end of programming to run code.
66  1.19  2004-11-03  Changes by Robert Adsett
67                    Add support for Analog Devices.
68                    Separate file load from programming.
69                    Change from a debug on/off flag to debug level
70                    Remove if(debug) tests and replace with DebugPrintf
71                    statements.
72                    Change serial I/O and timing so that the system
73                    dependancies are isolated to a few portability functions.
74                    Add support for binary serial I/O.
75                    Add doxygen support.
76  1.20  2004-11-07  Preparation for multiport booting (factory support)
77  1.21  2004-11-08  Bugfix from Robert Adsett
78                    BinaryLength was not initialized
79  1.22  2004-11-08  Changes from Cyril Holweck / Evgeny Sinelnikov
80                    Forgotten IspEnvironment-> and bugfixes if COMPILE_FOR_LINUX
81                    If COMPILE_FOR_LPC21, PhilipsDownload() 'acts as' main():
82                    - it should not be static and should return int.
83                    - no sub-function can use exit() but only return()
84                    Use 'char' instead of 'byte' ;)
85  1.23  2005-01-16  Build in automatic detection of LPC chiptype
86                    (needed for 256 KByte support)
87  1.24B 2005-06-02  Changes by Thiadmer Riemersma: completed support for other
88                    chip types (LPC213x series and others).
89  1.24C 2005-06-11  Changes by Thiadmer Riemersma: added the device ID codes for
90                    chip types LPC2131 and LPC2132.
91  1.25  2005-06-19  Martin Maurer: Setup more parameters in DCB,
92                    otherwise wrong code is downloaded (only Windows and Cygwin)
93                    when a previous program has changed these parameters
94                    Check exact string of "G 0 A\r\n0\r\n" instead of whole received buffer,
95                    to prevent checking of already received by program start
96                    (error on running program, but reports CMD_SUCCESS)
97                    Add ifdefs for all baudrates (needed only for high baudrate,
98                    which seem to be not available on Macs...)
99  1.26  2005-06-26  Martin Maurer:
100                    Correct check again: "G 0 A\r\n0\r\n" is cutted, because of reboot
101                    (error on running program, but reports CMD_SUCCESS)
102  1.27  2005-06-29  Martin Maurer:
103                    Add LPC chip ID's (thanks to Robert from Philips) for
104                    missing LPC213x and upcoming new LPC214x chips
105                    (currently untested, because i don't have access to these chips,
106                     please give me feedback !)
107  1.28  2005-07-27  Anders Rosvall / Embedded Artists AB:
108                    Changed the reset timeout to 500 ms when entering the bootloader.
109                    Some external reset controllers have quite long timeout periods,
110                    so extening the timeout delay would be a good thing.
111  1.29  2005-09-14  Rob Jansen:
112                    Added functionality to download to RAM and run from there.
113                    In LoadFile() added record types 04 (Extended Linear Address Record)
114                    and 05 (Start Linear Address Record), added address offset
115                    (IspEnvironment->BinaryOffset) and start address (...->StartAddress).
116                    Changed PhilipsDownload to skip all Flash prepare/erase/copy commands.
117                                    Note: Tested with VC7 only
118 1.30   2005-10-04  Rob Jansen:
119                    - forgot to change the version string in 1.29
120                                    - Wrong text in LoadFile corrected (printed text mentions record type 05,
121                                      this should be 04
122                                    - Changed LoadFile to accept multiple record types 04
123                                    - Changed LoadFile to check on memory size, will not load more than x MB
124                                      if linear extended address records are used
125 1.31   2005-11-13  Martin Maurer: Thanks to Frank Gutmann
126                    Updated number of sectors in device table
127                                    for LPC2194, LPC2292 and LPC2294
128 1.32   2005-12-02  Martin Maurer: Corrected missing control of RTS/DTR
129                    in case user selected -termonly and -control
130                    Small correction (typo in debug)
131 1.33   2006-10-01  Jean-Marc Koller:
132                    Added support for MacOS X (difference on how to set termios baudrate).
133 1.34   2006-10-01  Cyril Holweck:
134                    Made it compile again for lpc21isp
135                    Added const keyword to constant variables to make it better
136                    code for embeded target. (decrease RAM usage)
137                    Replaced all regular call to printf() by DebugPrintf()
138                    Removed call to scanf() (not much usefull and cost a lot to my target)
139 1.35   2006-22-01  Cyril Holweck
140                    Added feature for LPC21: will start downloading at Sector 1 and upward,
141                    to finish with Sector 0, the one containing the checksum controling BSL entry
142 1.36   2006-25-01  Cyril Holweck
143                    PhilipsDownload() will now return a unique error code for each error
144 1.37   2006-10-03  Jeroen Domburg
145                    Added LPC2103 (and only the 2103, I can't find the IDs for 2101/2102)
146                            Corrected a loop which occured if the program completely fits in sector 0
147 1.38   2007-01-05  Ray Molenkamp
148                    Added feature for LPC21: Wipe entire device before programming to enable
149                    reflashing of chips with the lpc codeprotection feature enabled.
150 1.39   2007-01-12  Martin Maurer
151                    Added initial support for new processors LPC23xx and LPC24xx
152
153 ******************************************************************************/
154
155 #define VERSION_STR     "1.39"
156
157 /* LPC_RAMSTART, LPC_RAMBASE
158  *
159  * Used in PhilipsDownload() to decide whether to Flash code or just place in in RAM
160  * (works for .hex files only)
161  *
162  * LPC_RAMSTART - the Physical start address of the SRAM
163  * LPC_RAMBASE  - the base address where downloading starts.
164  *                Note that any code in the .hex file that resides in 0x4000,0000 ~ 0x4000,0200
165  *                will _not_ be written to the LPCs SRAM.
166  *                This is due to the fact that 0x4000,0040 - 0x4000,0200 is used by the bootrom.
167  *                Any interrupt vectors must be copied to 0x4000,0000 and remapped to 0x0000,0000
168  *                by the startup code.
169  */
170 #define LPC_RAMSTART    0x40000000L
171 #define LPC_RAMBASE     0x40000200L
172
173 /* LPC_FLASHMASK
174  *
175  * LPC_FLASHMASK - bitmask to define the maximum size of the Filesize to download.
176  *                 LoadFile() will check any new segment address record (03) or extended linear
177  *                 address record (04) to see if the addressed 64 kByte data block still falls
178  *                 in the max. flash size.
179  *                 LoadFile() will not load any files that are larger than this size.
180  */
181 #define LPC_FLASHMASK  0xFFC00000 /* 22 bits = 4 MB */
182
183
184 #if defined(_WIN32) && !defined(__CYGWIN__)
185     #define COMPILE_FOR_WINDOWS
186     #define COMPILED_FOR ("Windows")
187 #elif defined(__CYGWIN__)
188     #define COMPILE_FOR_CYGWIN
189     #define COMPILED_FOR ("Cygwin")
190 #elif defined(__arm__) || defined(__thumb__)
191     #define COMPILE_FOR_LPC21
192     #define COMPILED_FOR ("ARM")
193     #define printf iprintf
194 #elif defined(__APPLE__)
195     #define COMPILE_FOR_LINUX
196     #define COMPILED_FOR ("Apple MacOS X")
197 #else
198     #define COMPILE_FOR_LINUX
199     #define COMPILED_FOR ("Linux")
200 #endif
201
202 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
203 #include <windows.h>
204 #include <io.h>
205 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
206
207 #if defined COMPILE_FOR_WINDOWS
208 #include <conio.h>
209 #endif // defined COMPILE_FOR_WINDOWS
210
211 #if defined COMPILE_FOR_LINUX
212 #include <sys/types.h>
213 #include <sys/stat.h>
214 #include <stdlib.h>
215 #include <string.h>
216 #include <strings.h>
217 #include <sys/ioctl.h>
218 #endif // defined COMPILE_FOR_LINUX
219
220 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
221 #include <termios.h>
222 #include <unistd.h>     // for read and return value of lseek
223 #include <sys/time.h>   // for select_time
224 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
225
226 #include <ctype.h>      // isdigit()
227 #include <stdio.h>      // stdout
228 #include <stdarg.h>
229 #include <time.h>
230
231 #if defined COMPILE_FOR_LPC21
232 #include <stdlib.h>
233 #include <string.h>
234 //#include <lpc_ioctl.h>  // if using libc serial port communication
235 #include "lpc21isp.h"   // if using propriatory serial port communication (customize attached lpc21isp.h)
236 #endif
237
238 #if !defined COMPILE_FOR_LPC21
239 #include <fcntl.h>
240 #endif
241
242 #ifndef O_BINARY
243 #define O_BINARY 0
244 #endif // O_BINARY
245
246 #ifndef DWORD
247 #define DWORD unsigned long
248 #endif // DWORD
249
250 #if defined COMPILE_FOR_LINUX
251 #define stricmp strcasecmp
252 #endif // defined COMPILE_FOR_LINUX
253
254
255 /* Return values used by PhilipsDownload(): reserving all values from 0x1000 to 0x1FFF */
256
257 #define NO_ANSWER_WDT       0x1000
258 #define NO_ANSWER_QM        0x1001
259 #define NO_ANSWER_SYNC      0x1002
260 #define NO_ANSWER_OSC       0x1003
261 #define NO_ANSWER_RBV       0x1004
262 #define NO_ANSWER_RPID      0x1005
263 #define ERROR_WRITE_DATA    0x1006
264 #define ERROR_WRITE_CRC     0x1007
265 #define ERROR_WRITE_CRC2    0x1008
266 #define PROGRAM_TOO_LARGE   0x1009
267
268 #define UNLOCK_ERROR        0x1100   /* return value is 0x1100 + philips ISP returned value (0 to 255) */
269 #define WRONG_ANSWER_PREP   0x1200   /* return value is 0x1200 + philips ISP returned value (0 to 255) */
270 #define WRONG_ANSWER_ERAS   0x1300   /* return value is 0x1300 + philips ISP returned value (0 to 255) */
271 #define WRONG_ANSWER_WRIT   0x1400   /* return value is 0x1400 + philips ISP returned value (0 to 255) */
272 #define WRONG_ANSWER_PREP2  0x1500   /* return value is 0x1500 + philips ISP returned value (0 to 255) */
273 #define WRONG_ANSWER_COPY   0x1600   /* return value is 0x1600 + philips ISP returned value (0 to 255) */
274 #define FAILED_RUN          0x1700   /* return value is 0x1700 + philips ISP returned value (0 to 255) */
275
276
277
278
279
280 typedef unsigned char BINARY;   /**< data type used for microcontroller
281                                 *  memory image.                        */
282
283 /*
284 debug levels
285 0 - very quiet          - Nothing gets printed at this level
286 1 - quiet               - Only error messages should be printed
287 2 - indicate progress   - Add progress messages
288 3 - first level debug   - Major level tracing
289 4 - second level debug  - Add detailed debugging
290 5 - log comm's          - log serial I/O
291 */
292
293 typedef enum
294 {
295     PHILIPS_ARM,
296     ANALOG_DEVICES_ARM
297 } TARGET;
298
299 typedef struct
300 {
301     unsigned long id;
302     unsigned Product;
303     unsigned FlashSize;     /* in kiB, for informational purposes only */
304     unsigned RAMSize;       /* in kiB, for informational purposes only */
305     unsigned FlashSectors;  /* total number of sectors */
306     unsigned MaxCopySize;   /* maximum size that can be copied to Flash in a single command */
307     const int *SectorTable; /* pointer to a sector table with constant the sector sizes */
308 } LPC_DEVICE_TYPE;
309
310 typedef struct
311 {
312
313 #if !defined COMPILE_FOR_LPC21
314     TARGET micro;                      /**< The type of micro that will be
315                                          * programmed.                           */
316     int debug_level;
317     unsigned char TerminalAfterUpload;
318     unsigned char FormatHex;
319     unsigned char ControlLines;
320     unsigned char LogFile;
321     char *input_file;                   /**< Name of the file to get input from. */
322     char *serial_port;                  /**< Name of the serial port to use to
323                                          * communicate with the microcontroller.
324                                          * Read from the command line.          */
325
326 #endif // !defined COMPILE_FOR_LPC21
327     unsigned char TerminalOnly;
328     unsigned char DetectOnly;
329     unsigned char WipeDevice;
330     int           DetectedDevice;       /* index in LPCtypes[] array */
331     char *baud_rate;                    /**< Baud rate to use on the serial
332                                          * port communicating with the
333                                          * microcontroller. Read from the
334                                          * command line.                        */
335
336     char *StringOscillator;             /**< Holds representation of oscillator
337                                           * speed from the command line.         */
338     BINARY *BinaryContent;              /**< Binary image of the                 */
339                                         /* microcontroller's memory.             */
340     unsigned long BinaryLength;
341         unsigned long BinaryOffset;
342         unsigned long StartAddress;
343
344 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
345     HANDLE hCom;
346 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
347
348 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
349     int fdCom;
350 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
351
352 #if defined COMPILE_FOR_LINUX
353     struct termios oldtio, newtio;
354 #endif // defined COMPILE_FOR_LINUX
355
356     unsigned serial_timeout_count;   /**< Local used to track
357                                       * timeouts on serial port read. */
358
359 } ISP_ENVIRONMENT;
360
361
362 static void DumpString(int level, const void *s, size_t size, const char *fmt, ...);
363 static void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s);
364 static void ReceiveComPort(ISP_ENVIRONMENT *IspEnvironment, void *Answer, unsigned long MaxSize, unsigned long *RealSize, unsigned long WantedNr0x0A,unsigned timeOutMilliseconds);
365 static void PhilipsOutputErrorMessage(unsigned char ErrorNumber);
366 static unsigned char GetErrorNumber(const char *Answer);
367 static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds);
368 static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment);
369 static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment);
370
371 #if !defined COMPILE_FOR_LPC21
372
373 static int debug_level = 2;
374
375 static void DebugPrintf( int level, const char *fmt, ...);
376 static void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment);
377 static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS);
378 static unsigned char Ascii2Hex(unsigned char c);
379 #endif
380
381 static const int SectorTable_210x[] = { 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
382                                         8192, 8192, 8192, 8192, 8192, 8192, 8192 };
383 static const int SectorTable_2103[] = { 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096 };
384 static const int SectorTable_211x[] = { 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
385                                         8192, 8192, 8192, 8192, 8192, 8192, 8192, };
386 static const int SectorTable_212x[] = { 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
387                                         65536, 65536, 8192, 8192, 8192, 8192, 8192, 8192,
388                                         8192 };
389 static const int SectorTable_213x[] = { 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
390                                         32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
391                                         32768, 32768, 32768, 32768, 32768, 32768, 4096, 4096,
392                                         4096, 4096, 4096 };
393 static int SectorTable_RAM[]  = { 65000 };
394
395 static LPC_DEVICE_TYPE LPCtypes[] =
396 {
397   { 0, 0, 0 },  /* unknown */
398   { 0x0004FF11, 2103,  32,  8,  8, 4096, SectorTable_2103 },
399   { 0xFFF0FF12, 2104, 128, 16, 15, 8192, SectorTable_210x },
400   { 0xFFF0FF22, 2105, 128, 32, 15, 8192, SectorTable_210x },
401   { 0xFFF0FF32, 2106, 128, 64, 15, 8192, SectorTable_210x },
402   { 0x0101FF12, 2114, 128, 16, 15, 8192, SectorTable_211x },
403   { 0x0201FF12, 2119, 128, 16, 15, 8192, SectorTable_211x },
404   { 0x0101FF13, 2124, 256, 16, 17, 8192, SectorTable_212x },
405   { 0x0201FF13, 2129, 256, 16, 17, 8192, SectorTable_212x },
406   { 0x0002FF01, 2131,  32,  8,  8, 4096, SectorTable_213x },
407   { 0x0002FF11, 2132,  64, 16,  9, 4096, SectorTable_213x },
408   { 0x0002FF12, 2134, 128, 16, 11, 4096, SectorTable_213x },
409   { 0x0002FF23, 2136, 256, 32, 15, 4096, SectorTable_213x },
410   { 0x0002FF25, 2138, 512, 32, 27, 4096, SectorTable_213x },
411   { 0x0402FF01, 2141,  32,  8,  8, 4096, SectorTable_213x },
412   { 0x0402FF11, 2142,  64, 16,  9, 4096, SectorTable_213x },
413   { 0x0402FF12, 2144, 128, 16, 11, 4096, SectorTable_213x },
414   { 0x0402FF23, 2146, 256, 40, 15, 4096, SectorTable_213x },
415   { 0x0402FF25, 2148, 512, 40, 27, 4096, SectorTable_213x },
416   { 0x0301FF13, 2194, 256, 16, 17, 8192, SectorTable_212x },
417   { 0x0301FF12, 2210,   0, 16,  0, 8192, SectorTable_211x }, /* table is a "don't care" */
418   { 0x0401FF12, 2212, 128, 16, 15, 8192, SectorTable_211x },
419   { 0x0601FF13, 2214, 256, 16, 17, 8192, SectorTable_212x },
420   /*            2290; same id as the LPC2210 */
421   { 0x0401FF13, 2292, 256, 16, 17, 8192, SectorTable_212x },
422   { 0x0501FF13, 2294, 256, 16, 17, 8192, SectorTable_212x },
423   { 0x0603FB02, 2364, 128, 34, 11, 4096, SectorTable_213x },
424   { 0x0603FB23, 2366, 256, 58, 15, 4096, SectorTable_213x },
425   { 0x0603FB25, 2368, 512, 58, 27, 4096, SectorTable_213x },
426   { 0x0703FF25, 2378, 512, 58, 27, 4096, SectorTable_213x },
427   /* { 0x0603FF35, 2458, 512, 98, 27, 4096, SectorTable_213x }, same id as 2468 ? */
428   { 0x0603FF35, 2468, 512, 98, 27, 4096, SectorTable_213x }
429 };
430
431 /************* Portability layer. Serial and console I/O differences    */
432 /* are taken care of here.                                              */
433
434 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
435 static int kbhit( void);
436 static int getch( void);
437 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
438
439 #if defined COMPILE_FOR_LINUX
440 static void Sleep(unsigned long MilliSeconds);
441 #endif // defined COMPILE_FOR_LINUX
442
443
444
445 #if !defined COMPILE_FOR_LPC21
446 static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
447 {
448     // Open COM-Port (different between Windows and Linux)
449
450 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
451     DCB    dcb;
452     COMMTIMEOUTS commtimeouts;
453
454     IspEnvironment->hCom = CreateFile(IspEnvironment->serial_port, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
455
456     if(IspEnvironment->hCom == INVALID_HANDLE_VALUE)
457     {
458         DebugPrintf( 1, "Can't open COM-Port %s ! - Error: %ld\n", IspEnvironment->serial_port, GetLastError());
459         exit(2);
460     }
461
462     DebugPrintf( 3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
463
464     GetCommState(IspEnvironment->hCom, &dcb);
465     dcb.BaudRate    = atol(IspEnvironment->baud_rate);
466     dcb.ByteSize    = 8;
467     dcb.StopBits    = ONESTOPBIT;
468     dcb.Parity      = NOPARITY;
469     dcb.fDtrControl = DTR_CONTROL_DISABLE;
470     dcb.fOutX       = FALSE;
471     dcb.fInX        = FALSE;
472     dcb.fNull       = FALSE;
473     dcb.fRtsControl = RTS_CONTROL_DISABLE;
474     if(SetCommState(IspEnvironment->hCom, &dcb) == 0)
475     {
476         DebugPrintf( 1, "Can't set baudrate %s ! - Error: %ld", IspEnvironment->baud_rate, GetLastError());
477         exit(3);
478     }
479
480     SetCommMask(IspEnvironment->hCom,EV_RXCHAR | EV_TXEMPTY);
481
482     commtimeouts.ReadIntervalTimeout         = MAXDWORD;
483     commtimeouts.ReadTotalTimeoutMultiplier  =    0;
484     commtimeouts.ReadTotalTimeoutConstant    =    1;
485     commtimeouts.WriteTotalTimeoutMultiplier =    0;
486     commtimeouts.WriteTotalTimeoutConstant   =    0;
487     SetCommTimeouts(IspEnvironment->hCom, &commtimeouts);
488
489 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
490
491 #if defined COMPILE_FOR_LINUX
492
493     IspEnvironment->fdCom = open(IspEnvironment->serial_port, O_RDWR | O_NOCTTY | O_NONBLOCK );
494
495     if(IspEnvironment->fdCom < 0)
496     {
497         DebugPrintf( 1, "Can't open COM-Port %s !\n", IspEnvironment->serial_port);
498         exit(2);
499     }
500
501     DebugPrintf( 3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
502
503         /* clear input & output buffers, then switch to "blocking mode" */
504         tcflush(IspEnvironment->fdCom, TCOFLUSH);
505         tcflush(IspEnvironment->fdCom, TCIFLUSH);
506         fcntl(IspEnvironment->fdCom, F_SETFL, fcntl(IspEnvironment->fdCom, F_GETFL) & ~O_NONBLOCK);
507
508     tcgetattr(IspEnvironment->fdCom, &IspEnvironment->oldtio); /* save current port settings */
509
510     bzero(&IspEnvironment->newtio, sizeof(IspEnvironment->newtio));
511     IspEnvironment->newtio.c_cflag = CS8 | CLOCAL | CREAD;
512
513 #ifdef __APPLE__
514 #define NEWTERMIOS_SETBAUDARTE(bps)     IspEnvironment->newtio.c_ispeed = IspEnvironment->newtio.c_ospeed = bps;
515 #else
516 #define NEWTERMIOS_SETBAUDARTE(bps)     IspEnvironment->newtio.c_cflag |= bps;
517 #endif
518
519     switch(atol(IspEnvironment->baud_rate))
520     {
521 #ifdef B1152000
522         case 1152000: NEWTERMIOS_SETBAUDARTE( B1152000 ); break;
523 #endif // B1152000
524 #ifdef B576000
525         case  576000: NEWTERMIOS_SETBAUDARTE( B576000 ); break;
526 #endif // B576000
527 #ifdef B230400
528         case  230400: NEWTERMIOS_SETBAUDARTE( B230400 ); break;
529 #endif // B230400
530 #ifdef B115200
531         case  115200: NEWTERMIOS_SETBAUDARTE( B115200 ); break;
532 #endif // B115200
533 #ifdef B57600
534         case   57600: NEWTERMIOS_SETBAUDARTE( B57600 ); break;
535 #endif // B57600
536 #ifdef B38400
537         case   38400: NEWTERMIOS_SETBAUDARTE( B38400 ); break;
538 #endif // B38400
539 #ifdef B19200
540         case   19200: NEWTERMIOS_SETBAUDARTE( B19200 ); break;
541 #endif // B19200
542 #ifdef B9600
543         case    9600: NEWTERMIOS_SETBAUDARTE( B9600 ); break;
544 #endif // B9600
545         default:
546         {
547             DebugPrintf( 1, "unknown baudrate %s\n", IspEnvironment->baud_rate);
548             exit(3);
549         }
550     }
551
552     IspEnvironment->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF;
553     IspEnvironment->newtio.c_oflag = 0;
554
555     /* set input mode (non-canonical, no echo,...) */
556     IspEnvironment->newtio.c_lflag = 0;
557
558     cfmakeraw(&IspEnvironment->newtio);
559     IspEnvironment->newtio.c_cc[VTIME]    = 1;   /* inter-character timer used */
560     IspEnvironment->newtio.c_cc[VMIN]     = 0;   /* blocking read until 0 chars received */
561
562     tcflush(IspEnvironment->fdCom, TCIFLUSH);
563     tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio);
564
565 #endif // defined COMPILE_FOR_LINUX
566 }
567
568 static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
569 {
570 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
571
572     CloseHandle(IspEnvironment->hCom);
573
574 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
575
576 #if defined COMPILE_FOR_LINUX
577
578         tcflush(IspEnvironment->fdCom, TCOFLUSH);
579         tcflush(IspEnvironment->fdCom, TCIFLUSH);
580     tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->oldtio);
581
582     close(IspEnvironment->fdCom);
583
584 #endif // defined COMPILE_FOR_LINUX
585 }
586
587 #endif // !defined COMPILE_FOR_LPC21
588
589 /***************************** SendComPortBlock *************************/
590 /**  Sends a block of bytes out the opened com port.
591 \param [in] s block to send.
592 \param [in] n size of the block.
593 */
594 static void SendComPortBlock(ISP_ENVIRONMENT *IspEnvironment, const void *s, size_t n)
595 {
596 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
597
598     unsigned long realsize;
599
600 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
601
602     DumpString( 4, s, n, "Sending ");
603
604 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
605
606     WriteFile(IspEnvironment->hCom, s, n, &realsize, NULL);
607
608 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
609
610 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
611
612     write(IspEnvironment->fdCom, s, n);
613
614 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
615 }
616
617 /***************************** SendComPort ******************************/
618 /**  Sends a string out the opened com port.
619 \param [in] s string to send.
620 */
621 static void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s)
622 {
623     SendComPortBlock( IspEnvironment, s, strlen(s));
624 }
625
626
627 /***************************** ReceiveComPortBlock **********************/
628 /**  Receives a buffer from the open com port. Returns all the characters
629 ready (waits for up to 'n' milliseconds before accepting that no more
630 characters are ready) or when the buffer is full. 'n' is system dependant,
631 see SerialTimeout routines.
632 \param [out] answer buffer to hold the bytes read from the serial port.
633 \param [in] max_size the size of buffer pointed to by answer.
634 \param [out] real_size pointer to a long that returns the amout of the
635 buffer that is actually used.
636 */
637 static void ReceiveComPortBlock( ISP_ENVIRONMENT *IspEnvironment,
638                                  void *answer, unsigned long max_size,
639                                  unsigned long *real_size)
640 {
641
642 #if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
643
644     ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
645
646 #endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
647
648 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
649
650     *real_size = read(IspEnvironment->fdCom, answer, max_size);
651
652 #endif // defined COMPILE_FOR_LINUX
653
654
655     DumpString( 5, answer, (*real_size), "Read(Length=%ld): ", (*real_size));
656
657     if( *real_size == 0)
658     {
659         SerialTimeoutTick( IspEnvironment );
660     }
661 }
662
663
664 /***************************** SerialTimeoutSet *************************/
665 /**  Sets (or resets) the timeout to the timout period requested.  Starts
666 counting to this period.  This timeout support is a little odd in that the
667 timeout specifies the accumulated deadtime waiting to read not the total
668 time waiting to read. They should be close enought to the same for this
669 use. Used by the serial input routines, the actual counting takes place in
670 ReceiveComPortBlock.
671 \param [in] timeout_milliseconds the time in milliseconds to use for
672 timeout.  Note that just because it is set in milliseconds doesn't mean
673 that the granularity is that fine.  In many cases (particularly Linux) it
674 will be coarser.
675 */
676 static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds)
677 {
678
679 #if defined COMPILE_FOR_LINUX
680     IspEnvironment->serial_timeout_count = timeout_milliseconds/100;
681 #elif defined COMPILE_FOR_LPC21
682     IspEnvironment->serial_timeout_count = timeout_milliseconds*200;
683 #else
684     IspEnvironment->serial_timeout_count = timeout_milliseconds;
685 #endif
686 }
687
688 /***************************** SerialTimeoutTick ************************/
689 /**  Performs a timer tick.  In this simple case all we do is count down
690 with protection against underflow and wrapping at the low end.
691 */
692 static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment)
693 {
694     if( IspEnvironment->serial_timeout_count <= 1)
695     {
696         IspEnvironment->serial_timeout_count = 0;
697     }
698     else
699     {
700         IspEnvironment->serial_timeout_count--;
701     }
702 }
703
704 /***************************** SerialTimeoutCheck ***********************/
705 /**  Check to see if the serial timeout timer has run down.
706 \retval 1 if timer has run out.
707 \retval 0 if timer still has time left.
708 */
709 static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment)
710 {
711     if( IspEnvironment->serial_timeout_count == 0)
712     {
713         return 1;
714     }
715     return 0;
716 }
717
718
719 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
720 /***************************** getch ************************************/
721 /** Replacement for the common dos function of the same name. Reads a
722 single unbuffered character from the 'keyboard'.
723 \return The character read from the keyboard.
724 */
725 static int getch(void)
726 {
727     char ch;
728     struct termios origtty, tty;
729
730     /* store the current tty settings */
731     tcgetattr(0, &origtty);
732
733     /* start with the current settings */
734     tty = origtty;
735     /* make modifications to put it in raw mode, turn off echo */
736     tty.c_lflag &= ~ICANON;
737     tty.c_lflag &= ~ECHO;
738     tty.c_lflag &= ~ISIG;
739     tty.c_cc[VMIN] = 1;
740     tty.c_cc[VTIME] = 0;
741
742     /* put the settings into effect */
743     tcsetattr(0, TCSADRAIN, &tty);
744
745     /* Read in one character */
746     read(0,&ch,1);
747
748     /* reset the tty to its original settings */
749     tcsetattr(0, TCSADRAIN, &origtty);
750
751     return ch;
752 }
753 #endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
754
755 #if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
756 /***************************** kbhit ************************************/
757 /** Replacement for the common dos function of the same name. Indicates if
758 there are characters to be read from the console.
759 \retval 0 No characters ready.
760 \retval 1 Characters from the console ready to be read.
761 */
762 static int kbhit(void)
763 {
764     /* return 0 for no key pressed, 1 for key pressed */
765     int return_value = 0;
766
767     /* variables to store the current tty state, create a new one */
768     struct termios origtty, tty;
769     /* time struct for the select() function, to only wait a little while */
770     struct timeval select_time;
771     /* file descriptor variable for the select() call */
772     fd_set readset;
773
774     /* we're only interested in STDIN */
775     FD_ZERO(&readset);
776     FD_SET(STDIN_FILENO, &readset);