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