]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/commitdiff
Add LPC21ISP to host
authorMartin Meloun <meloumar@cmp.felk.cvut.cz>
Thu, 22 Aug 2013 14:08:50 +0000 (16:08 +0200)
committerMartin Meloun <meloumar@cmp.felk.cvut.cz>
Thu, 22 Aug 2013 14:08:50 +0000 (16:08 +0200)
12 files changed:
host/app/Makefile.omk
host/app/lpc21lisp/Makefile [new file with mode: 0644]
host/app/lpc21lisp/Makefile.omk [new file with mode: 0644]
host/app/lpc21lisp/adprog.c [new file with mode: 0644]
host/app/lpc21lisp/adprog.h [new file with mode: 0644]
host/app/lpc21lisp/lpc21isp.c [new file with mode: 0644]
host/app/lpc21lisp/lpc21isp.h [new file with mode: 0644]
host/app/lpc21lisp/lpcprog.c [new file with mode: 0644]
host/app/lpc21lisp/lpcprog.h [new file with mode: 0644]
host/app/lpc21lisp/lpcterm.c [new file with mode: 0644]
host/app/lpc21lisp/lpcterm.h [new file with mode: 0644]
host/config.omk

index 8d691bdcbd35b37ce398fac42c24cf15e8ede701..9272f1d5bde7ac3eab1f74b2d8ac53cb07bc4cfa 100644 (file)
@@ -1 +1 @@
-SUBDIRS = rocon_cmd usb_sendhex
+SUBDIRS = rocon_cmd usb_sendhex lpc21lisp
diff --git a/host/app/lpc21lisp/Makefile b/host/app/lpc21lisp/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/host/app/lpc21lisp/Makefile.omk b/host/app/lpc21lisp/Makefile.omk
new file mode 100644 (file)
index 0000000..145180b
--- /dev/null
@@ -0,0 +1,9 @@
+default_CONFIG = CONFIG_APP_LPC21LISP=x
+
+ifeq ($(CONFIG_APP_LPC21LISP),y)
+
+bin_PROGRAMS = lpc21isp
+
+lpc21isp_SOURCES = lpc21isp.c adprog.c lpcprog.c lpcterm.c
+
+endif #CONFIG_APP_LPC21LISP
diff --git a/host/app/lpc21lisp/adprog.c b/host/app/lpc21lisp/adprog.c
new file mode 100644 (file)
index 0000000..c6b99b7
--- /dev/null
@@ -0,0 +1,325 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          adprog.c\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#if defined(_WIN32)\r
+#if !defined __BORLANDC__\r
+#include "StdAfx.h"\r
+#endif\r
+#endif // defined(_WIN32)\r
+#include "lpc21isp.h"\r
+\r
+#ifdef AD_SUPPORT\r
+#include "adprog.h"\r
+\r
+/***************************** AnalogDevicesSync ************************/\r
+/**  Attempt to synchronize with an Analog Device ARM micro.  Sends a\r
+backspace and reads back the microcontrollers response.  Performs\r
+multiple retries. Exits the program on error, returns to caller in the\r
+case of success.\r
+*/\r
+static void AnalogDevicesSync(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+    BINARY sync;                        /* Holds sync command.          */\r
+    AD_SYNC_RESPONSE response;          /* Response from micro.         */\r
+    int sync_attempts;                  /* Number of retries.           */\r
+\r
+    /*  Make sure we don't read garbage later instead of the        */\r
+    /* response we expect from the micro.                           */\r
+    ClearSerialPortBuffers(IspEnvironment);\r
+\r
+    DebugPrintf(2, "Synchronizing\n"); /* Progress report.             */\r
+\r
+    sync = ANALOG_DEVICES_SYNC_CHAR;    /* Build up sync command.       */\r
+\r
+    /*  Perform the actual sync attempt.  First send the sync       */\r
+    /* character, the attempt to read back the response.  For the   */\r
+    /* AD ARM micro this is a fixed length block.  If response is   */\r
+    /* received attempt to validate it by comparing the first       */\r
+    /* characters to those expected.  If the received block does    */\r
+    /* not validate or is incomplete empty the serial buffer and    */\r
+    /* retry.                                                       */\r
+    for (sync_attempts = 0; sync_attempts < 5; sync_attempts++)\r
+    {\r
+        SendComPortBlock(IspEnvironment, &sync, 1);\r
+\r
+        if (ReceiveComPortBlockComplete(IspEnvironment, &response, sizeof(response),\r
+            500) == 0)\r
+        {\r
+\r
+            if (memcmp(response.product_id, ANALOG_DEVICES_SYNC_RESPONSE,\r
+                ANALOG_DEVICES_SYNC_SIZE) == 0)\r
+            {\r
+                return;\r
+            }\r
+            else\r
+            {\r
+                DumpString(3, &response, sizeof(response),\r
+                    "Unexpected response to sync attempt ");\r
+            }\r
+        }\r
+        else\r
+        {\r
+            DebugPrintf(3, "No (or incomplete) answer on sync attempt\n");\r
+        }\r
+\r
+        ClearSerialPortBuffers(IspEnvironment);\r
+    }\r
+\r
+    DebugPrintf(1, "No (or unacceptable) answer on sync attempt\n");\r
+    exit(4);\r
+}\r
+\r
+typedef struct {\r
+    char start1;\r
+    char start2;\r
+    BINARY bytes;\r
+    char cmd;\r
+    BINARY address_h;\r
+    BINARY address_u;\r
+    BINARY address_m;\r
+    BINARY address_l;\r
+    BINARY data[251];\r
+} AD_PACKET;\r
+\r
+/***************************** AnalogDevicesFormPacket ******************/\r
+/**  Create an Analog Devices communication packet from the constituent\r
+elements.\r
+\param [in] cmd The command being sent, one of 'E' for erase, 'W' for\r
+write, 'V' for verify or 'R' for run..\r
+\param [in] no_bytes the number of data bytes to send with the command in\r
+the packet.\r
+\param [in] address the address to apply the command to.\r
+\param [in] data the data to send with the packet, may be null if no_bytes\r
+is zero.\r
+\param[out] packet that will be filled.\r
+*/\r
+static void AnalogDevicesFormPacket(ISP_ENVIRONMENT *IspEnvironment,\r
+                                                char cmd, int no_bytes, unsigned int address,\r
+                                                const void *data, AD_PACKET *packet)\r
+{\r
+    BINARY checksum;\r
+    const BINARY *data_in;\r
+    int i;\r
+\r
+    (void)IspEnvironment; /* never used in this function */\r
+\r
+    /*  Some sanity checking on the arguments.  These should only   */\r
+    /* fail if there is a bug in the caller.                        */\r
+    /*  Check 1) that the number of data bytes is in an acceptable  */\r
+    /* range, 2) that we have a non-null pointer if data is being   */\r
+    /* put in the packet and 3) that we have a non-null pointer to  */\r
+    /* the packet to be filled. We just exit with an error message  */\r
+    /* if any of these tests fail.                                  */\r
+    if ((no_bytes < 0) || (no_bytes > 250))\r
+    {\r
+        DebugPrintf(1,\r
+            "The number of bytes (%d) passed to FormPacket is invalid.\n",\r
+            no_bytes);\r
+        exit(-1);\r
+    }\r
+    if ((data == 0) && (no_bytes != 0))\r
+    {\r
+        DebugPrintf(1,\r
+            "A null pointer to data paased to FormPacket when data was expected.\n");\r
+        exit(-1);\r
+    }\r
+    if (packet == 0)\r
+    {\r
+        DebugPrintf(1,\r
+            "A null packet pointer was passed to FormPacket.\n");\r
+        exit(-1);\r
+    }\r
+\r
+    checksum = 0;               /*  Checksum starts at zero.            */\r
+\r
+    data_in = (BINARY*) data;             /*  Pointer pun so we can walk through  */\r
+    /* the data.                            */\r
+\r
+    packet->start1 = 0x7;       /*  The start of the packet is constant.*/\r
+    packet->start2 = 0xE;\r
+\r
+    /*  Fill in the rest of the packet and calculate the checksum   */\r
+    /* as we go.                                                    */\r
+\r
+    /* The number of bytes is the number of data bytes + the        */\r
+    /* address bytes + the command byte.                            */\r
+    packet->bytes = (BINARY)(no_bytes + 5);\r
+\r
+    checksum += packet->bytes;\r
+\r
+    /*  The command for the packet being sent.  No error checking   */\r
+    /* done on this.                                                */\r
+    packet->cmd = cmd;\r
+\r
+    checksum += cmd;\r
+\r
+    /*  Now break up the address and place in the proper packet     */\r
+    /* locations.                                                   */\r
+    packet->address_l = (BINARY)(address & 0xFF);\r
+    packet->address_m = (BINARY)((address >> 8) & 0xFF);\r
+    packet->address_u = (BINARY)((address >> 16) & 0xFF);\r
+    packet->address_h = (BINARY)((address >> 24) & 0xFF);\r
+\r
+    checksum += packet->address_l;\r
+    checksum += packet->address_m;\r
+    checksum += packet->address_u;\r
+    checksum += packet->address_h;\r
+\r
+    /*  Copy the data bytes into the packet.  We could use memcpy   */\r
+    /* but we have to calculate the checksum anyway.                */\r
+    for (i = 0; i < no_bytes; i++)\r
+    {\r
+        packet->data[i] = data_in[i];\r
+        checksum += data_in[i];\r
+    }\r
+\r
+    /*  Finally, add the checksum to the end of the packet.         */\r
+    packet->data[i] = (BINARY)-checksum;\r
+}\r
+\r
+/***************************** AnalogDevicesSendPacket ******************/\r
+/**  Send a previously form Analog Devices communication.  Retry a\r
+couple of times if needed but fail by exiting the program if no ACK is\r
+forthcoming.\r
+\param [in] packet the packet to send.\r
+*/\r
+static void AnalogDevicesSendPacket(ISP_ENVIRONMENT *IspEnvironment,\r
+                                                const AD_PACKET * packet)\r
+{\r
+    BINARY response;\r
+    int retry = 0;\r
+\r
+    do {\r
+        retry++;\r
+\r
+        /*  Make sure we don't read garbage later instead of    */\r
+        /* the response we expect from the micro.               */\r
+        ClearSerialPortBuffers(IspEnvironment);\r
+\r
+        /*  Send the packet, the size is the number of data     */\r
+        /* bytes in the packet plus 3 bytes worth of header     */\r
+        /* plus checksum.                                       */\r
+        SendComPortBlock(IspEnvironment, packet, packet->bytes + 4);\r
+\r
+        /*  Receive the response and check, return to caller    */\r
+        /* if successful.                                       */\r
+        if (ReceiveComPortBlockComplete(IspEnvironment, &response, 1, 5000) == 0)\r
+        {\r
+            if (response == ANALOG_DEVICES_ACK)\r
+            {\r
+                DebugPrintf(3, "Packet Sent\n");\r
+                return;\r
+            }\r
+            if (response != ANALOG_DEVICES_NAK)\r
+            {\r
+                DebugPrintf(3, "Unexpected response to packet (%x)\n", (int)response);\r
+            }\r
+            DebugPrintf(2, "*");\r
+        }\r
+    } while (retry < 3);\r
+\r
+    DebugPrintf(1, "Send packet failed\n");\r
+    exit(-1);\r
+}\r
+\r
+/***************************** AnalogDevicesErase ***********************/\r
+/**  Erase the Analog Devices micro.  We take the simple way out and\r
+just erase the whole thing.\r
+*/\r
+static void AnalogDevicesErase(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+    BINARY pages;\r
+    AD_PACKET packet;\r
+\r
+    pages = 0;\r
+    DebugPrintf(2, "Erasing .. ");\r
+    AnalogDevicesFormPacket(IspEnvironment, 'E', 1, 0, &pages, &packet);\r
+    AnalogDevicesSendPacket(IspEnvironment, &packet);\r
+    DebugPrintf(2, "Erased\n");\r
+}\r
+\r
+#define AD_PACKET_SIZE (250)\r
+\r
+/***************************** AnalogDevicesWrite ***********************/\r
+/**  Write the program.\r
+\param [in] data the program to download to the micro.\r
+\param [in] address where to start placing the program.\r
+\param [in] bytes the size of the progrm to download.\r
+*/\r
+static void AnalogDevicesWrite(ISP_ENVIRONMENT *IspEnvironment,\r
+                                         const void *data, long address, size_t bytes)\r
+{\r
+    AD_PACKET packet;\r
+    const BINARY *prog_data;\r
+\r
+    DebugPrintf(2, "Writing %d bytes ", bytes);\r
+    prog_data = (const BINARY*) data;\r
+    while (bytes > AD_PACKET_SIZE)\r
+    {\r
+        AnalogDevicesFormPacket(IspEnvironment, 'W', AD_PACKET_SIZE, address, prog_data, &packet);\r
+        AnalogDevicesSendPacket(IspEnvironment, &packet);\r
+        address += AD_PACKET_SIZE;\r
+        prog_data += AD_PACKET_SIZE;\r
+        bytes -= AD_PACKET_SIZE;\r
+        DebugPrintf(2, ".");\r
+    }\r
+    if (bytes > 0)\r
+    {\r
+        AnalogDevicesFormPacket(IspEnvironment, 'W', bytes, address, prog_data, &packet);\r
+        AnalogDevicesSendPacket(IspEnvironment, &packet);\r
+        DebugPrintf(2, ".");\r
+    }\r
+}\r
+\r
+/***************************** AnalogDevicesDownload ********************/\r
+/**  Perform the download into an Analog Devices micro.  As a quick and\r
+* dirty hack against flash relocations at 0x80000\r
+* \return 0 if ok, error code else\r
+* \ToDo: possible to implement the return value instead of calling\r
+* exit() in sub-functions\r
+*/\r
+int AnalogDevicesDownload(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+    AnalogDevicesSync(IspEnvironment);\r
+    AnalogDevicesErase(IspEnvironment);\r
+    if (IspEnvironment->BinaryLength > 0x80000)\r
+    {\r
+        DebugPrintf(2, "Note:  Flash remapped 0x80000 to 0.\n");\r
+        AnalogDevicesWrite(IspEnvironment, IspEnvironment->BinaryContent + 0x80000, 0, IspEnvironment->BinaryLength-0x80000);\r
+    }\r
+    else\r
+    {\r
+        AnalogDevicesWrite(IspEnvironment, IspEnvironment->BinaryContent, 0, IspEnvironment->BinaryLength);\r
+    }\r
+    return (0);\r
+}\r
+#endif // AD_SUPPORT\r
diff --git a/host/app/lpc21lisp/adprog.h b/host/app/lpc21lisp/adprog.h
new file mode 100644 (file)
index 0000000..efd296c
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          adprog.h\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#define ANALOG_DEVICES_SYNC_CHAR                ((BINARY)0x08)\r
+#define ANALOG_DEVICES_SYNC_RESPONSE        ("ADuC")\r
+#define ANALOG_DEVICES_SYNC_SIZE                (strlen(ANALOG_DEVICES_SYNC_RESPONSE))\r
+#define ANALOG_DEVICES_ACK                        0x6\r
+#define ANALOG_DEVICES_NAK                        0x7\r
+\r
+typedef struct\r
+{\r
+    BINARY product_id[15];\r
+    BINARY version[3];\r
+    BINARY reserved[4];\r
+    BINARY terminator[2];\r
+} AD_SYNC_RESPONSE;\r
+\r
+int AnalogDevicesDownload(ISP_ENVIRONMENT *IspEnvironment);\r
diff --git a/host/app/lpc21lisp/lpc21isp.c b/host/app/lpc21lisp/lpc21isp.c
new file mode 100644 (file)
index 0000000..4357185
--- /dev/null
@@ -0,0 +1,2479 @@
+/******************************************************************************
+
+Project:           Portable command line ISP for NXP LPC family
+                   and Analog Devices ADUC70xx
+
+Filename:          lpc21isp.c
+
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,
+                   GCC Cygwin, GCC Linux, GCC ARM ELF
+
+Author:            Martin Maurer (Martin.Maurer@clibb.de)
+
+Copyright:         (c) Martin Maurer 2003-2013, All rights reserved
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com
+
+    This file is part of lpc21isp.
+
+    lpc21isp is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    any later version.
+
+    lpc21isp is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    and GNU General Public License along with lpc21isp.
+    If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#if defined(_WIN32)
+#if !defined __BORLANDC__
+#include "StdAfx.h"        // Precompiled Header for WIN32
+#endif
+#endif // defined(_WIN32)
+#include "lpc21isp.h"   // if using propriatory serial port communication (customize attached lpc21isp.h)
+#include "adprog.h"
+#include "lpcprog.h"
+#include "lpcterm.h"
+
+/*
+Change-History:
+
+1.00  2004-01-08  Initial Version, tested for MSVC6/7 and GCC under Cygwin
+1.01  2004-01-10  Porting to Linux (at least compiling must work)
+1.02  2004-01-10  Implemented conversion intel hex format -> binary
+1.03  2004-01-25  Preparation to upload to public website
+1.04  2004-02-12  Merged in bugfixes by Soeren Gust
+1.05  2004-03-14  Implement printing of error codes as text / strings
+1.06  2004-03-09  Merged in bugfixes by Charles Manning:
+                  The '?' sychronisation does not reliably respond to the first '?'.
+                  I added some retries.
+                  The LPC2106 sometimes responds to the '?' by echoing them back.
+                  This sometimes causes an attempt to match "?Synchonized".
+                  Added code to strip off any leading '?'s.
+                  Timeouts were too long.
+                  Change from RTS/CTS to no flow control.
+                  Done because many/most people will use only 3-wire comms.
+                  Added some progress tracing.
+1.07  2004-03-14  Implement handling of control lines for easier booting
+1.08  2004-04-01  Bugfix for upload problem
+1.09  2004-04-03  Redesign of upload routine
+                  Now always 180 byte blocks are uploaded, to prevent
+                  small junks in uuencoding
+1.10  2004-04-03  Clear buffers before sending commands to LPC21xx,
+                  this prevents synchronizing errors when previously loaded
+                  program does a lot of output, so FIFO of PC runs full
+1.11  2004-04-03  Small optimization for controlling reset line
+                  otherwise termonly starts LPC twice, free PC buffers
+1.12  2004-04-04  Add switch to enable logging terminal output to lpc21isp.log
+1.13  2004-05-19  Merged in improvement by Charles Manning:
+                  Instead of exiting the wrong hex file size is corrected
+1.14  2004-07-07  Merged in improvement by Alex Holden:
+                  Remove little/big endian dependancy
+1.15  2004-09-27  Temporary improvement by Cyril Holweck:
+                  Removed test (data echoed = data transmited) on the main
+                  data transfert, since this was the biggest failure
+                  reason and is covered by checksome anyway.
+                  Added COMPILE_FOR_LPC21, to have target dump it's own
+                  memory to stdout.
+1.16  2004-10-09  Merged in bugfix / improvement by Sinelnikov Evgeny
+                  I found out that Linux and Windows serial port initialization
+                  are different with pinouts states. My board don't get
+                  reset signal at first cycle of DTR pinout moving.
+                  And I add this moving to initalization cycle.
+1.17  2004-10-21  Changes by Cyril Holweck
+                  Divide main, take out the real programming function, that can
+                  also be used by a target to copy its own code to another.
+1.18  2004-10-26  Changes by Cyril Holweck
+                  Added a "G 0 A\r\n" at end of programming to run code.
+1.19  2004-11-03  Changes by Robert Adsett
+                  Add support for Analog Devices.
+                  Separate file load from programming.
+                  Change from a debug on/off flag to debug level
+                  Remove if (debug) tests and replace with DebugPrintf
+                  statements.
+                  Change serial I/O and timing so that the system
+                  dependancies are isolated to a few portability functions.
+                  Add support for binary serial I/O.
+                  Add doxygen support.
+1.20  2004-11-07  Preparation for multiport booting (factory support)
+1.21  2004-11-08  Bugfix from Robert Adsett
+                  BinaryLength was not initialized
+1.22  2004-11-08  Changes from Cyril Holweck / Evgeny Sinelnikov
+                  Forgotten IspEnvironment-> and bugfixes if COMPILE_FOR_LINUX
+                  If COMPILE_FOR_LPC21, PhilipsDownload() 'acts as' main():
+                  - it should not be static and should return int.
+                  - no sub-function can use exit() but only return ()
+                  Use 'char' instead of 'byte' ;)
+1.23  2005-01-16  Build in automatic detection of LPC chiptype
+                  (needed for 256 KByte support)
+1.24B 2005-06-02  Changes by Thiadmer Riemersma: completed support for other
+                  chip types (LPC213x series and others).
+1.24C 2005-06-11  Changes by Thiadmer Riemersma: added the device ID codes for
+                  chip types LPC2131 and LPC2132.
+1.25  2005-06-19  Martin Maurer: Setup more parameters in DCB,
+                  otherwise wrong code is downloaded (only Windows and Cygwin)
+                  when a previous program has changed these parameters
+                  Check exact string of "G 0 A\r\n0\r\n" instead of whole received buffer,
+                  to prevent checking of already received by program start
+                  (error on running program, but reports CMD_SUCCESS)
+                  Add ifdefs for all baudrates (needed only for high baudrate,
+                  which seem to be not available on Macs...)
+1.26  2005-06-26  Martin Maurer:
+                  Correct check again: "G 0 A\r\n0\r\n" is cutted, because of reboot
+                  (error on running program, but reports CMD_SUCCESS)
+1.27  2005-06-29  Martin Maurer:
+                  Add LPC chip ID's (thanks to Robert from Philips) for
+                  missing LPC213x and upcoming new LPC214x chips
+                  (currently untested, because i don't have access to these chips,
+                  please give me feedback !)
+1.28  2005-07-27  Anders Rosvall / Embedded Artists AB:
+                  Changed the reset timeout to 500 ms when entering the bootloader.
+                  Some external reset controllers have quite long timeout periods,
+                  so extening the timeout delay would be a good thing.
+1.29  2005-09-14  Rob Jansen:
+                  Added functionality to download to RAM and run from there.
+                  In LoadFile() added record types 04 (Extended Linear Address Record)
+                  and 05 (Start Linear Address Record), added address offset
+                  (IspEnvironment->BinaryOffset) and start address (...->StartAddress).
+                  Changed PhilipsDownload to skip all Flash prepare/erase/copy commands.
+                  Note: Tested with VC7 only
+1.30   2005-10-04 Rob Jansen:
+                  - forgot to change the version string in 1.29
+                  - Wrong text in LoadFile corrected (printed text mentions record type 05,
+                    this should be 04
+                  - Changed LoadFile to accept multiple record types 04
+                  - Changed LoadFile to check on memory size, will not load more than x MB
+                    if linear extended address records are used
+1.31   2005-11-13 Martin Maurer: Thanks to Frank Gutmann
+                  Updated number of sectors in device table
+                  for LPC2194, LPC2292 and LPC2294
+1.32   2005-12-02 Martin Maurer: Corrected missing control of RTS/DTR
+                  in case user selected -termonly and -control
+                  Small correction (typo in debug)
+1.33   2006-10-01 Jean-Marc Koller:
+                  Added support for MacOS X (difference on how to set termios baudrate).
+1.34   2006-10-01  Cyril Holweck:
+                  Made it compile again for lpc21isp
+                  Added const keyword to constant variables to make it better
+                  code for embeded target. (decrease RAM usage)
+                  Replaced all regular call to printf() by DebugPrintf()
+                  Removed call to scanf() (not much usefull and cost a lot to my target)
+1.35   2006-22-01 Cyril Holweck
+                  Added feature for LPC21: will start downloading at Sector 1 and upward,
+                  to finish with Sector 0, the one containing the checksum controling BSL entry
+1.36   2006-25-01 Cyril Holweck
+                  PhilipsDownload() will now return a unique error code for each error
+1.37   2006-10-03 Jeroen Domburg
+                  Added LPC2103 (and only the 2103, I can't find the IDs for 2101/2102)
+                  Corrected a loop which occured if the program completely fits in sector 0
+1.38   2007-01-05 Ray Molenkamp
+                  Added feature for LPC21: Wipe entire device before programming to enable
+                  reflashing of chips with the lpc codeprotection feature enabled.
+1.39   2007-01-12 Martin Maurer
+                  Added initial support for new processors LPC23xx and LPC24xx
+1.40   2007-01-22 Martin Maurer
+                  Correction of chip id of LPC2458
+1.41   2007-01-28 Jean-Marc Koller
+                  Modified Terminal() to disable ECHO with termios only once, instead of
+                  modifying and restoring termios in each getch and kbhit call (which caused
+                  a strange echo behaviour in MacOS X).
+1.42   2007-01-28 Rob Probin
+                  Added -localecho command to allow local echoing in terminal mode for use
+                  where target does not echo back keystrokes.
+1.43   2007-01-29 Martin Maurer
+                  Moved keyboard handling routines to own subroutines,
+                  so they can be used during aborting synchronisation.
+                  Newest cygwin made problems, StringOscillator always contained '\0x0d'
+                  at the end, when calling lpc21isp from batch file
+1.44   2007-02-23 Yang Yang
+                  Added feature for LPC21: Verify the data in Flash after every writes
+                  to sector. To detect errors in writing to Flash ROM.
+1.45   2007-02-25 Martin Maurer
+                  Replace printf syntax of DumpString by a simple pointer to a string
+                  printf syntax is a nice thing, but it is not working :-(
+                  and therefore makes debugging much more difficult...
+                  Moved VERSION_STR to top of file to avoid possible cosmetical errors
+1.46   2007-02-25 Martin Maurer
+                  Again corrected debug output: should solve output of
+                  (FFFFFFB5) instead of (B5)
+1.47   2007-02-27 Robert Adsett
+                  Raised timeout on AD send packet function.
+1.48   2007-04-20 Martin Maurer
+                  Thanks to Josef Wolf for preventing to overwrite over end of array
+1.49   2007-10-16 New Option -halfduplex allow single wire using.
+                  Implemented and tested only for Windows. Data Resend implemented.
+1.50   2007-10-31 Changes by Simon Ellwood
+                  Formated the code for readablity
+                  Fixed some c++ compiler issues
+1.51   2007-11-20 Changes by Simon Ellwood
+                  Split into seperate files
+                  Made more modular so when used in an embedded mode only the required code is built
+1.52   2008-01-22 Changes by Manuel Koeppen
+                  Made compileable again for linux and windows
+                  Fixed bug in ClearSerialPortBuffers (linux)
+1.53   2008-02-25 Changes by Michael Roth
+                  Get priority of debug messages with -control right
+1.54   2008-03-03 Martin Maurer
+                  Try to bring lpc21isp back to a useable state in Windows, Cygwin, Linux and Mac OS.
+                  Merged in changes by Erika Stefanini, which were done only for old version 1.49:
+                  Added device ids for revision B chips
+1.55   2008-03-03 Martin Maurer
+                  Thanks to Fausto Marzoli, bugfix for compiling latest version under Linux
+1.56   2008-04-01 Steve Franks
+                  Integrate FreeBSD patch.
+                  Add support for swapping and/or inverting RTS & DTR
+1.57   2008-04-06 Mauricio Scaff
+                  Changed OpenSerialPort to work with MacOS
+                  Corrected the number of sectors in some 512K devices (28 instead of 27)
+                  Added support for LPC2387 and LPC2388
+                  Defined BL error 19 (Code Protected)
+1.58   2008-05-10 Herbert Demmel dh2@demmel.com
+                  I had the special requirement to integrate the program into my own Windows
+                  software compiled with Borland C++ Builder 5. I had to do some minor changes
+                  for Borland (see defined __BORLANDC__) and modified to code slightly to have
+                  some simple callbacks for screen i/o (see define INTEGRATED_IN_WIN_APP).
+                  Please note that I do *not* check / modify the part for AnalogDevices !!
+                  Besides that I fixed some minor issues:
+                  added dcb.fOutxCtsFlow = FALSE and dcb.fOutxDsrFlow = FALSE (sometimes required)
+                  Now comparing one character less of answer to "Now launching ... code" command
+1.59   2008-07-07 Peter Hayward
+                  Fixed freeze under Windows XP SP2 by removing redundant call to SetCommMask.
+1.60   2008-07-21 Martin Maurer
+                  Added uptodate part ids for LPC2458, LPC2468 and LPC2478
+                  Add comment "obsolete" for older part ids for LPC2458 and LPC2468
+                  Add ", " between compile date and time
+1.61   2008-10-21 Fausto Marzoli (thanks to Geoffrey Wossum for the patches)
+                  Fix for compiling latest version under Linux and "ControlLinesSwapped" issue
+1.62   2008-11-19 Martin Maurer
+                  Added (untested) support for LPC2109
+                  Added (untested) support for LPC2361 / LPC2362
+                  Heavy update of part identification number of LPC23xx and LPC24xx
+                  Correct bug, that hex file must exist, when "-detectonly" is used
+                  Correct Makefile.vc: use /Fe instead of -o
+1.63   2008-11-23 Martin Maurer
+                  Changed to GNU Lesser General Public License
+1.64   2009-01-19 Steve Franks
+                  __FREEBSD__ changed to __FreeBSD__ at some point, plus other com port fixes
+1.65   2009-03-26 Vito Marolda
+                  Added pre-erasure of sector 0 to invalidate checksum before starting
+                  modification of the other sectors, so that the bootloader restarts
+                  if programming gets aborted while writing on a non-empty part.
+1.66   2009-03-26 Vito Marolda
+                  Corrected interpretation of intel hex record 03 which is execution start address
+                  and not data segment address
+1.67   2009-04-19 SASANO Takayoshi
+                  Add OpenBSD support
+1.68   2009-05-17 Martin Maurer
+                  Merge in changes done by Bruno Quoitin (baudrate problem when __APPLE__ is used)
+                  Remove TABs from source code and replaced them with spaces
+1.69   2009-06-18 Martin Maurer
+                  Add support for LPC17xx devices
+1.70   2009-06-29 Martin Maurer
+                  Further improvement of LPC17xx support
+                  Workaround for booter (4.1) of LPC17xx, which does not echo all sent characters (0D,0A,...)
+                  ISP command GO seems to be broken:
+                  Sending 'G 196 T(0A)'
+                  Answer(Length=15): 'G 196 T(0A)0(0D)(0A)'
+                  leads to 'prefetch_abort_exception(0D)(0A)1FFF07A5'
+                  No solution known...need your help here...
+                  Manual workaround: Use DTR and RTS toggling to start application (e.g. 2 batch files)
+1.71   2009-07-19 Martin Maurer
+                  Added LPC17xx with CPUID starting with 0x26 (not according user manual)
+1.72   2009-09-14 Martin Maurer
+                  Add support for LPC13xx devices
+1.73   2009-09-14 Martin Maurer
+                  Correct again (hopefully the last time) the CPUIDs for some LPC17xx devices
+                  (Now according to User Manual LPC17xx Version 00.07 (31 July 2009))
+1.74   2009-09-14 Mario Ivancic
+                  Added support for multiple HEX files, besed on internal version 1.37B.
+                  NOTE: this feature is used in production in 1.37B but is not tested in this version.
+                  Added numeric debug level command line switch -debugn, n=[0-5]
+                  Added command line scitch -try n to specify nQuestionMarks limit. Default: 100
+                  Merged in DoNotStart patch from cgommel_new
+                  Static functions declarations moved from lpc21isp.h to this file
+                  Modified LoadFile() to return error_code instead exit(1)
+                  Removed IspEnvironment.debug_level, all code uses global debug_level
+1.75   2010-01-05 Martin Maurer
+                  Added support for LPC11xx devices (not tested at all)
+                  Changed Product in LPC_DEVICE_TYPE from number to string to distinguish new LPC11 devices
+                  Changed "unsigned" to "unsigned int" in LPC_DEVICE_TYPE
+1.76   2010-02-01 Published test version without source code
+1.77   2010-02-01 Martin Maurer
+                  Corrected chip id of LPC1342 and LPC1343
+                  Added a new chip type for LPC11xx and LPC13xx microcontrollers
+                  Use higher area of RAM with LPC11xx and LPC13xx, because lower RAM is occupied by ISP
+                  Add code to lpcprog.c to read unique id, but not yet activate.
+                  Adapt block sizes for copying for each model of LPC11xx and LPC13xx
+1.78   2010-02-16 Martin Maurer
+                  Corrected chip id of LPC1751
+                  Added support for LPC1759, LPC1767 and LPC1769
+1.79   2010-02-19 Andrew Pines
+                  Added __APPLE__ flag to CFLAGS in Makefile to detect and handle OS X
+                  Added -Wall to Makefile to report warnings more comprehensively
+                  Added #define in lpc21isp.h to substitute strnicmp with strncasecmp (needed for Unix)
+                  Fixed a few format specifiers in lpcprog.c to eliminate some warnings
+1.80   2010-03-04 Philip Munts
+                  Added entries to LPCtypes[] in lpcprog.c for obsolete revisions of LPC2364/6/8/78.
+                  Added entry to LPCtypes[] in lpcprog.c for new LPC2387.
+1.81   2011-03-30 Mario Ivancic
+                  As per message #517 from Thiadmer Riemersma, removed WaitForWatchDog and WatchDogSeconds
+                  in PhilipsDownload().
+1.82   2011-06-25 Moses McKnight
+                  Corrected MaxCopySize for a number of the LPC11xx series
+                  Added support for several more LPC11xx and LPC11Cxx series
+1.83   2011-08-02 Martin Maurer
+                  Thanks to Conurus for detecting and fixing a bug with patching checksum
+                  (patching was too early, chip id was not yet available)
+                  (Re-)Added code to start downloaded via "G 0 T", when using LPC1xxx
+                  (Starting code at position 0 seems to work, compare to comment of version 1.70)
+                  Changed some occurances of Philips to NXP
+                  Added -static to Makefile (thanks to Camilo)
+                  Added support for LPC1311/01 and LPC1313/01 (they have separate identifiers)
+                  Correct flash size of LPC1342 to 16 KByte (thanks to Decio)
+                  Abort programming when unknown NXP chip id is detected
+1.84   2012-09-27 Philip Munts
+                  Added chip id's for more LPC11xx parts, per UM10398 Rev. 11 26 July 2012
+1.85   2012-12-13 Philip Munts
+                  Fixed conditional compilation logic in lpc21isp.h to allow compiling for ARM Linux.
+1.86   2012-12-14 diskrepairman
+                  Added devices: LPC1114/203 LPC1114/303 LPC1114/323 LPC1114/333 LPC1115/303
+1.87   2012-12-18 Philip Munts
+                  Added a section of code to ResetTarget() in lpc21isp.c to allow using Linux GPIO pin
+                  to control reset and ISP.
+1.88   2013-04-25 Torsten Lang, Uwe Schneider GmbH
+                  Fixed answer evaluation
+                  Added sector tables for LPC1833
+                  XON/XOFF handling according to LPC manual
+                  Changed COMMTIMEOUTS settings according to MS help
+                  Changed waiting code from tick counting to system time usage
+                  Set MM timers to 1ms resolution (otherwise waiting in the serial driver is limited to multiples of 10ms)
+                  Send all commands with <CR><LF> according to NXP UM
+                  Change answer evaluation to match at least LPC17xx and LPC18xx families (LPC17xx just mirrors the first character of
+                    the LF sequence, LPC18xx mirrors the first character and adds an <LF> which then will lead to a <CR><LF><LF>
+                    sequence, all other lines are terminated with <CR><LF> as documented)
+                  Change answer formatting by filtering leading <LF> characters because they can be left over from a previous response
+                  Store residual data of an answer (required for the J command which will deliver two words in case of the LPC18xx)
+                  Expanded configuration table by second identification word and usage flag
+                  Do a two stage scan in case that a device with two identification words is detected
+1.89   2013-06-27 Martin Maurer
+                  Thanks to Manuel and Henri for bugfixes and speed-ups
+                  Bugfix: In case of LPC8XX, XON/XOFF handling must be switched off,
+                  otherwise download gets broken, because XON/XOFF are filtered out...
+1.90   2013-06-27 Martin Maurer
+                  Add checksum calculation for LPC8XX
+                  winmm function only available in MSVC, put ifdefs around
+                  Workaround for lost characters of LPC8XX
+1.91   2013-06-28 Torsten Lang, Uwe Schneider GmbH
+                  Minor bugfix for the residual data handling
+1.92   2013-06-29 Martin Maurer
+                  Thanks to Phil for reporting Linux compile errors
+                  Update README
+1.93   2013-07-05 Andrew Pines
+                  changed Makefile to exclude "-static" from CFLAGS when building for OS X
+                  changed serial timeout for *nix to use select
+                  added -boothold argument to assert ISP throughtout programming sequence
+                  added support for -try<n> command line argument (was in help, didn't actually work)
+1.94   2013-08-10 Martin Maurer
+                  Add (assumed) part id values for LPC4333 and LPC4337
+                  Correct table entries for all LPC43xx part id numbers
+                  (missing flag for two word part ids and second word for LPC4333 and LPC4353)
+                  Merge in optimization (thanks to Stefan) to skip empty sectors
+                  Correct help output of "-boothold"
+                  Add workaround table entry for LPC4357 and word1 equal to 0x0EF60000
+                  Bugfix for wrong check of word0/word1 combination
+                  Correct a lot entries in lpc property table of LPC18xx and LPC43xx
+                  LPC18xx and LPC43xx: Add warning message, that wipe erases only bank A
+
+*/
+
+// Please don't use TABs in the source code !!!
+
+// Don't forget to update the version string that is on the next line
+#define VERSION_STR "1.94"
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+static char RxTmpBuf[256];        // save received data to this buffer for half-duplex
+char * pRxTmpBuf = RxTmpBuf;
+#endif
+
+#if !defined COMPILE_FOR_LPC21
+int debug_level = 2;
+#endif
+
+static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS);
+static unsigned char Ascii2Hex(unsigned char c);
+
+#ifdef COMPILE_FOR_WINDOWS
+static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds);
+static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment);
+#endif // COMPILE_FOR_WINDOWS
+
+static int AddFileHex(ISP_ENVIRONMENT *IspEnvironment, const char *arg);
+static int AddFileBinary(ISP_ENVIRONMENT *IspEnvironment, const char *arg);
+static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat);
+
+/************* Portability layer. Serial and console I/O differences    */
+/* are taken care of here.                                              */
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
+{
+    DCB    dcb;
+    COMMTIMEOUTS commtimeouts;
+
+#ifdef _MSC_VER
+    /* Torsten Lang 2013-05-06 Switch to higher timer resolution (we want to use 1ms timeouts in the serial device driver!) */
+    (void)timeBeginPeriod(1UL);
+#endif // _MSC_VER
+
+    IspEnvironment->hCom = CreateFile(IspEnvironment->serial_port, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
+
+    if (IspEnvironment->hCom == INVALID_HANDLE_VALUE)
+    {
+        DebugPrintf(1, "Can't open COM-Port %s ! - Error: %ld\n", IspEnvironment->serial_port, GetLastError());
+        exit(2);
+    }
+
+    DebugPrintf(3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
+
+    GetCommState(IspEnvironment->hCom, &dcb);
+    dcb.BaudRate    = atol(IspEnvironment->baud_rate);
+    dcb.ByteSize    = 8;
+    dcb.StopBits    = ONESTOPBIT;
+    dcb.Parity      = NOPARITY;
+    dcb.fDtrControl = DTR_CONTROL_DISABLE;
+    dcb.fOutX       = TRUE; // TL TODO - according to LPC manual! FALSE;
+    dcb.fInX        = TRUE; // TL TODO - according to LPC manual! FALSE;
+    dcb.fNull       = FALSE;
+    dcb.fRtsControl = RTS_CONTROL_DISABLE;
+
+    // added by Herbert Demmel - iF CTS line has the wrong state, we would never send anything!
+    dcb.fOutxCtsFlow = FALSE;
+    dcb.fOutxDsrFlow = FALSE;
+
+    if (SetCommState(IspEnvironment->hCom, &dcb) == 0)
+    {
+        DebugPrintf(1, "Can't set baudrate %s ! - Error: %ld", IspEnvironment->baud_rate, GetLastError());
+        exit(3);
+    }
+
+   /*
+    *  Peter Hayward 02 July 2008
+    *
+    *  The following call is only needed if the WaitCommEvent
+    *  or possibly the GetCommMask functions are used.  They are
+    *  *not* in this implimentation.  However, under Windows XP SP2
+    *  on my laptop the use of this call causes XP to freeze (crash) while
+    *  this program is running, e.g. in section 5/6/7 ... of a largish
+    *  download.  Removing this *unnecessary* call fixed the problem.
+    *  At the same time I've added a call to SetupComm to request
+    *  (not necessarity honoured) the operating system to provide
+    *  large I/O buffers for high speed I/O without handshaking.
+    *
+    *   SetCommMask(IspEnvironment->hCom,EV_RXCHAR | EV_TXEMPTY);
+    */
+    SetupComm(IspEnvironment->hCom, 32000, 32000);
+
+    SetCommMask(IspEnvironment->hCom, EV_RXCHAR | EV_TXEMPTY);
+
+    // Torsten Lang 2013-05-06: ReadFile may hang indefinitely with MAXDWORD/0/1/0/0 on FTDI devices!!!
+    commtimeouts.ReadIntervalTimeout         = MAXDWORD;
+    commtimeouts.ReadTotalTimeoutMultiplier  = MAXDWORD;
+    commtimeouts.ReadTotalTimeoutConstant    =    1;
+    commtimeouts.WriteTotalTimeoutMultiplier =    0;
+    commtimeouts.WriteTotalTimeoutConstant   =    0;
+    SetCommTimeouts(IspEnvironment->hCom, &commtimeouts);
+}
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LINUX
+static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
+{
+    IspEnvironment->fdCom = open(IspEnvironment->serial_port, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+    if (IspEnvironment->fdCom < 0)
+    {
+        int err = errno;
+        DebugPrintf(1, "Can't open COM-Port %s ! (Error: %dd (0x%X))\n", IspEnvironment->serial_port, err, err);
+        exit(2);
+    }
+
+    DebugPrintf(3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
+
+    /* clear input & output buffers, then switch to "blocking mode" */
+    tcflush(IspEnvironment->fdCom, TCOFLUSH);
+    tcflush(IspEnvironment->fdCom, TCIFLUSH);
+    fcntl(IspEnvironment->fdCom, F_SETFL, fcntl(IspEnvironment->fdCom, F_GETFL) & ~O_NONBLOCK);
+
+    tcgetattr(IspEnvironment->fdCom, &IspEnvironment->oldtio); /* save current port settings */
+
+    bzero(&IspEnvironment->newtio, sizeof(IspEnvironment->newtio));
+    IspEnvironment->newtio.c_cflag = CS8 | CLOCAL | CREAD;
+
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+
+    if(cfsetspeed(&IspEnvironment->newtio,(speed_t) strtol(IspEnvironment->baud_rate,NULL,10))) {
+                  DebugPrintf(1, "baudrate %s not supported\n", IspEnvironment->baud_rate);
+                  exit(3);
+              };
+#else
+
+#ifdef __APPLE__
+#define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_ispeed = IspEnvironment->newtio.c_ospeed = bps;
+#else
+#define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_cflag |= bps;
+#endif
+
+    switch (atol(IspEnvironment->baud_rate))
+    {
+#ifdef B1152000
+          case 1152000: NEWTERMIOS_SETBAUDARTE(B1152000); break;
+#endif // B1152000
+#ifdef B576000
+          case  576000: NEWTERMIOS_SETBAUDARTE(B576000); break;
+#endif // B576000
+#ifdef B230400
+          case  230400: NEWTERMIOS_SETBAUDARTE(B230400); break;
+#endif // B230400
+#ifdef B115200
+          case  115200: NEWTERMIOS_SETBAUDARTE(B115200); break;
+#endif // B115200
+#ifdef B57600
+          case   57600: NEWTERMIOS_SETBAUDARTE(B57600); break;
+#endif // B57600
+#ifdef B38400
+          case   38400: NEWTERMIOS_SETBAUDARTE(B38400); break;
+#endif // B38400
+#ifdef B19200
+          case   19200: NEWTERMIOS_SETBAUDARTE(B19200); break;
+#endif // B19200
+#ifdef B9600
+          case    9600: NEWTERMIOS_SETBAUDARTE(B9600); break;
+#endif // B9600
+
+          // Special value
+          // case   32000: NEWTERMIOS_SETBAUDARTE(32000); break;
+
+          default:
+              {
+                  DebugPrintf(1, "unknown baudrate %s\n", IspEnvironment->baud_rate);
+                  exit(3);
+              }
+    }
+
+#endif
+
+    IspEnvironment->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF;
+    IspEnvironment->newtio.c_oflag = 0;
+
+    /* set input mode (non-canonical, no echo,...) */
+    IspEnvironment->newtio.c_lflag = 0;
+
+    cfmakeraw(&IspEnvironment->newtio);
+    IspEnvironment->newtio.c_cc[VTIME]    = 1;   /* inter-character timer used */
+    IspEnvironment->newtio.c_cc[VMIN]     = 0;   /* blocking read until 0 chars received */
+
+    tcflush(IspEnvironment->fdCom, TCIFLUSH);
+    if(tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio))
+    {
+       DebugPrintf(1, "Could not change serial port behaviour (wrong baudrate?)\n");
+       exit(3);
+    }
+
+}
+#endif // defined COMPILE_FOR_LINUX
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
+{
+    CloseHandle(IspEnvironment->hCom);
+
+#ifdef _MSC_VER
+    /* Torsten Lang 2013-05-06 Switch back timer resolution */
+    (void)timeEndPeriod(1UL);
+#endif // _MSC_VER
+}
+
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LINUX
+static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
+{
+    tcflush(IspEnvironment->fdCom, TCOFLUSH);
+    tcflush(IspEnvironment->fdCom, TCIFLUSH);
+    tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->oldtio);
+
+    close(IspEnvironment->fdCom);
+}
+#endif // defined COMPILE_FOR_LINUX
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+void ControlXonXoffSerialPort(ISP_ENVIRONMENT *IspEnvironment, unsigned char XonXoff)
+{
+    DCB dcb;
+
+    GetCommState(IspEnvironment->hCom, &dcb);
+
+    if(XonXoff)
+    {
+        dcb.fOutX = TRUE;
+        dcb.fInX  = TRUE;
+    }
+    else
+    {
+        dcb.fOutX = FALSE;
+        dcb.fInX  = FALSE;
+    }
+
+    if (SetCommState(IspEnvironment->hCom, &dcb) == 0)
+    {
+        DebugPrintf(1, "Can't set XonXoff ! - Error: %ld", GetLastError());
+        exit(3);
+    }
+}
+
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LINUX
+void ControlXonXoffSerialPort(ISP_ENVIRONMENT *IspEnvironment, unsigned char XonXoff)
+{
+    if(tcgetattr(IspEnvironment->fdCom, &IspEnvironment->newtio))
+    {
+       DebugPrintf(1, "Could not get serial port behaviour\n");
+       exit(3);
+    }
+
+    if(XonXoff)
+    {
+      IspEnvironment->newtio.c_iflag |= IXON;
+      IspEnvironment->newtio.c_iflag |= IXOFF;
+    }
+    else
+    {
+      IspEnvironment->newtio.c_iflag &= ~IXON;
+      IspEnvironment->newtio.c_iflag &= ~IXOFF;
+    }
+
+    if(tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio))
+    {
+       DebugPrintf(1, "Could not set serial port behaviour\n");
+       exit(3);
+    }
+}
+#endif // defined COMPILE_FOR_LINUX
+
+/***************************** SendComPortBlock *************************/
+/**  Sends a block of bytes out the opened com port.
+\param [in] s block to send.
+\param [in] n size of the block.
+*/
+void SendComPortBlock(ISP_ENVIRONMENT *IspEnvironment, const void *s, size_t n)
+{
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+    unsigned long realsize;
+    size_t m;
+    unsigned long rxsize;
+    char * pch;
+    char * rxpch;
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+    DumpString(4, s, n, "Sending ");
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+    if (IspEnvironment->HalfDuplex == 0)
+    {
+        WriteFile(IspEnvironment->hCom, s, n, &realsize, NULL);
+    }
+    else
+    {
+        pch = (char *)s;
+        rxpch = RxTmpBuf;
+        pRxTmpBuf = RxTmpBuf;
+
+        // avoid buffer otherflow
+        if (n > sizeof (RxTmpBuf))
+            n = sizeof (RxTmpBuf);
+
+        for (m = 0; m < n; m++)
+        {
+            WriteFile(IspEnvironment->hCom, pch, 1, &realsize, NULL);
+
+            if ((*pch != '?') || (n != 1))
+            {
+                do
+                {
+                    ReadFile(IspEnvironment->hCom, rxpch, 1, &rxsize, NULL);
+                }while (rxsize == 0);
+            }
+            pch++;
+            rxpch++;
+        }
+        *rxpch = 0;        // terminate echo string
+    }
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
+
+    write(IspEnvironment->fdCom, s, n);
+
+#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
+}
+
+/***************************** SendComPort ******************************/
+/**  Sends a string out the opened com port.
+\param [in] s string to send.
+*/
+void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s)
+{
+    SendComPortBlock(IspEnvironment, s, strlen(s));
+}
+
+/***************************** SerialTimeoutTick ************************/
+/**  Performs a timer tick.  In this simple case all we do is count down
+with protection against underflow and wrapping at the low end.
+*/
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment)
+{
+    if (IspEnvironment->serial_timeout_count <= 1)
+    {
+        IspEnvironment->serial_timeout_count = 0;
+    }
+    else
+    {
+        IspEnvironment->serial_timeout_count--;
+    }
+}
+#endif
+
+/***************************** ReceiveComPortBlock **********************/
+/**  Receives a buffer from the open com port. Returns all the characters
+ready (waits for up to 'n' milliseconds before accepting that no more
+characters are ready) or when the buffer is full. 'n' is system dependant,
+see SerialTimeout routines.
+\param [out] answer buffer to hold the bytes read from the serial port.
+\param [in] max_size the size of buffer pointed to by answer.
+\param [out] real_size pointer to a long that returns the amout of the
+buffer that is actually used.
+*/
+static void ReceiveComPortBlock(ISP_ENVIRONMENT *IspEnvironment,
+                                          void *answer, unsigned long max_size,
+                                          unsigned long *real_size)
+{
+    char tmp_string[32];
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+    if (IspEnvironment->HalfDuplex == 0)
+        ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
+    else
+    {
+        *real_size = strlen (pRxTmpBuf);
+        if (*real_size)
+        {
+            if (max_size >= *real_size)
+            {
+                strncpy((char*) answer, pRxTmpBuf, *real_size);
+                RxTmpBuf[0] = 0;
+                pRxTmpBuf = RxTmpBuf;
+            }
+            else
+            {
+                strncpy((char*) answer, pRxTmpBuf, max_size);
+                *real_size = max_size;
+                pRxTmpBuf += max_size;
+            }
+        }
+        else
+            ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
+    }
+
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LPC21
+
+    *real_size = read(IspEnvironment->fdCom, answer, max_size);
+
+#endif // defined COMPILE_FOR_LPC21
+
+#if defined COMPILE_FOR_LINUX
+    {
+        fd_set
+            readSet;
+        struct timeval
+            timeVal;
+
+        FD_ZERO(&readSet);                             // clear the set
+        FD_SET(IspEnvironment->fdCom,&readSet);        // add this descriptor to the set
+        timeVal.tv_sec=0;                              // set up the timeout waiting for one to come ready (500ms)
+        timeVal.tv_usec=500*1000;
+        if(select(FD_SETSIZE,&readSet,NULL,NULL,&timeVal)==1)    // wait up to 500 ms or until our data is ready
+        {
+            *real_size=read(IspEnvironment->fdCom, answer, max_size);
+        }
+        else
+        {
+            // timed out, show no characters received and timer expired
+            *real_size=0;
+            IspEnvironment->serial_timeout_count=0;
+        }
+    }
+#endif // defined COMPILE_FOR_LINUX
+
+    sprintf(tmp_string, "Read(Length=%ld): ", (*real_size));
+    DumpString(5, answer, (*real_size), tmp_string);
+
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+    if (*real_size == 0)
+    {
+        SerialTimeoutTick(IspEnvironment);
+    }
+#endif
+}
+
+
+/***************************** SerialTimeoutSet *************************/
+/**  Sets (or resets) the timeout to the timout period requested.  Starts
+counting to this period.  This timeout support is a little odd in that the
+timeout specifies the accumulated deadtime waiting to read not the total
+time waiting to read. They should be close enought to the same for this
+use. Used by the serial input routines, the actual counting takes place in
+ReceiveComPortBlock.
+\param [in] timeout_milliseconds the time in milliseconds to use for
+timeout.  Note that just because it is set in milliseconds doesn't mean
+that the granularity is that fine.  In many cases (particularly Linux) it
+will be coarser.
+*/
+static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds)
+{
+#if defined COMPILE_FOR_LINUX
+    IspEnvironment->serial_timeout_count = timeout_milliseconds / 100;
+#elif defined COMPILE_FOR_LPC21
+    IspEnvironment->serial_timeout_count = timeout_milliseconds * 200;
+#else
+#ifdef _MSC_VER
+    IspEnvironment->serial_timeout_count = timeGetTime() + timeout_milliseconds;
+#else
+    IspEnvironment->serial_timeout_count = timeout_milliseconds;
+#endif // _MSC_VER
+#endif
+}
+
+
+
+/***************************** SerialTimeoutCheck ***********************/
+/**  Check to see if the serial timeout timer has run down.
+\retval 1 if timer has run out.
+\retval 0 if timer still has time left.
+*/
+static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment)
+{
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+#ifdef _MSC_VER
+    if ((signed long)(IspEnvironment->serial_timeout_count - timeGetTime()) < 0)
+    {
+        return 1;
+    }
+#else
+    if (IspEnvironment->serial_timeout_count == 0)
+    {
+        return 1;
+    }
+#endif // _MSC_VER
+#else
+    if (IspEnvironment->serial_timeout_count == 0)
+    {
+        return 1;
+    }
+#endif
+    return 0;
+}
+
+
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
+/***************************** getch ************************************/
+/** Replacement for the common dos function of the same name. Reads a
+single unbuffered character from the 'keyboard'.
+\return The character read from the keyboard.
+*/
+int getch(void)
+{
+    char ch;
+
+    /* Read in one character */
+    read(0,&ch,1);
+
+    return ch;
+}
+#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
+/***************************** kbhit ************************************/
+/** Replacement for the common dos function of the same name. Indicates if
+there are characters to be read from the console.
+\retval 0 No characters ready.
+\retval 1 Characters from the console ready to be read.
+*/
+int kbhit(void)
+{
+    /* return 0 for no key pressed, 1 for key pressed */
+    int return_value = 0;
+
+    /* time struct for the select() function, to only wait a little while */
+    struct timeval select_time;
+    /* file descriptor variable for the select() call */
+    fd_set readset;
+
+    /* we're only interested in STDIN */
+    FD_ZERO(&readset);
+    FD_SET(STDIN_FILENO, &readset);
+
+    /* how long to block for - this must be > 0.0, but could be changed
+    to some other setting. 10-18msec seems to work well and only
+    minimally load the system (0% CPU loading) */
+    select_time.tv_sec = 0;
+    select_time.tv_usec = 10;
+
+    /* is there a keystroke there? */
+    if (select(1, &readset, NULL, NULL, &select_time))
+    {
+        /* yes, remember it */
+        return_value = 1;
+    }
+
+
+    /* return with what we found out */
+    return return_value;
+}
+struct termios keyboard_origtty;
+#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
+
+
+/***************************** PrepareKeyboardTtySettings ***************/
+/** Set the keyboard tty to be able to check for new characters via kbhit
+getting them via getch
+*/
+
+void PrepareKeyboardTtySettings(void)
+{
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
+    /* store the current tty settings */
+    if (!tcgetattr(0, &keyboard_origtty))
+    {
+        struct termios tty;
+        /* start with the current settings */
+        tty = keyboard_origtty;
+        /* make modifications to put it in raw mode, turn off echo */
+        tty.c_lflag &= ~ICANON;
+        tty.c_lflag &= ~ECHO;
+        tty.c_lflag &= ~ISIG;
+        tty.c_cc[VMIN] = 1;
+        tty.c_cc[VTIME] = 0;
+
+        /* put the settings into effect */
+        tcsetattr(0, TCSADRAIN, &tty);
+    }
+#endif
+}
+
+
+/***************************** ResetKeyboardTtySettings *****************/
+/** Reset the keyboard tty to original settings
+*/
+void ResetKeyboardTtySettings(void)
+{
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
+    /* reset the tty to its original settings */
+    tcsetattr(0, TCSADRAIN, &keyboard_origtty);
+#endif
+}
+
+
+#if !defined COMPILE_FOR_LPC21
+/***************************** ControlModemLines ************************/
+/**  Controls the modem lines to place the microcontroller into various
+states during the programming process.
+error rather abruptly terminates the program.
+\param [in] DTR the state to set the DTR line to.
+\param [in] RTS the state to set the RTS line to.
+*/
+static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS)
+{
+    //handle wether to invert the control lines:
+    DTR ^= IspEnvironment->ControlLinesInverted;
+    RTS ^= IspEnvironment->ControlLinesInverted;
+
+    //handle wether to swap the control lines
+    if (IspEnvironment->ControlLinesSwapped)
+    {
+        unsigned char tempRTS;
+        tempRTS = RTS;
+        RTS = DTR;
+        DTR = tempRTS;
+    }
+
+#if defined COMPILE_FOR_LINUX
+    int status;
+
+    if (ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
+    {
+        DebugPrintf(3, "ioctl get ok, status = %X\n",status);
+    }
+    else
+    {
+        DebugPrintf(1, "ioctl get failed\n");
+    }
+
+    if (DTR) status |=  TIOCM_DTR;
+    else    status &= ~TIOCM_DTR;
+
+    if (RTS) status |=  TIOCM_RTS;
+    else    status &= ~TIOCM_RTS;
+
+    if (ioctl(IspEnvironment->fdCom, TIOCMSET, &status) == 0)
+    {
+        DebugPrintf(3, "ioctl set ok, status = %X\n",status);
+    }
+    else
+    {
+        DebugPrintf(1, "ioctl set failed\n");
+    }
+
+    if (ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
+    {
+        DebugPrintf(3, "ioctl get ok, status = %X\n",status);
+    }
+    else
+    {
+        DebugPrintf(1, "ioctl get failed\n");
+    }
+
+#endif // defined COMPILE_FOR_LINUX
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+    if (DTR) EscapeCommFunction(IspEnvironment->hCom, SETDTR);
+    else    EscapeCommFunction(IspEnvironment->hCom, CLRDTR);
+
+    if (RTS) EscapeCommFunction(IspEnvironment->hCom, SETRTS);
+    else    EscapeCommFunction(IspEnvironment->hCom, CLRRTS);
+
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+
+#if defined COMPILE_FOR_LPC21
+    LPC_RESET(DTR);
+    LPC_BSL(RTS);
+#endif
+
+    DebugPrintf(3, "DTR (%d), RTS (%d)\n", DTR, RTS);
+}
+
+
+/***************************** ClearSerialPortBuffers********************/
+/**  Empty the serial port buffers.  Cleans things to a known state.
+*/
+void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment)
+{
+#if defined COMPILE_FOR_LINUX
+    /* variables to store the current tty state, create a new one */
+    struct termios origtty, tty;
+
+    /* store the current tty settings */
+    tcgetattr(IspEnvironment->fdCom, &origtty);
+
+    // Flush input and output buffers
+    tty=origtty;
+    tcsetattr(IspEnvironment->fdCom, TCSAFLUSH, &tty);
+
+    /* reset the tty to its original settings */
+    tcsetattr(IspEnvironment->fdCom, TCSADRAIN, &origtty);
+#endif // defined COMPILE_FOR_LINUX
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+    PurgeComm(IspEnvironment->hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
+}
+#endif // !defined COMPILE_FOR_LPC21
+
+
+#if defined COMPILE_FOR_LINUX
+/***************************** Sleep ************************************/
+/**  Provide linux replacement for windows function.
+\param [in] Milliseconds the time to wait for in milliseconds.
+*/
+void Sleep(unsigned long MilliSeconds)
+{
+    usleep(MilliSeconds*1000); //convert to microseconds
+}
+#endif // defined COMPILE_FOR_LINUX
+
+
+#if defined COMPILE_FOR_LPC21
+/**  Provide linux replacement for windows function.
+\note I implement that one in my private header file today...
+\param [in] Milliseconds the time to wait for in milliseconds.
+*/
+/*static void Sleep(unsigned long MilliSeconds)
+{
+#   warning Sleep function not implemented
+}
+*/
+#endif // defined COMPILE_FOR_LPC21
+
+
+
+/************* Applicationlayer.                                        */
+
+#if !defined COMPILE_FOR_LPC21
+/***************************** DebugPrintf ******************************/
+/**  Prints a debug string depending the current debug level. The higher
+the debug level the more detail that will be printed.  Each print
+has an associated level, the higher the level the more detailed the
+debugging information being sent.
+\param [in] level the debug level of the print statement, if the level
+is less than or equal to the current debug level it will be printed.
+\param [in] fmt a standard printf style format string.
+\param [in] ... the usual printf parameters.
+*/
+#if !defined INTEGRATED_IN_WIN_APP
+void DebugPrintf(int level, const char *fmt, ...)
+{
+    va_list ap;
+
+    if (level <= debug_level)
+    {
+        char pTemp[2000];
+        va_start(ap, fmt);
+        //vprintf(fmt, ap);
+        vsprintf(pTemp, fmt, ap);
+        TRACE(pTemp);
+        va_end(ap);
+        fflush(stdout);
+    }
+}
+#endif
+#endif // !defined COMPILE_FOR_LPC21
+
+
+/***************************** ReceiveComPort ***************************/
+/**  Receives a buffer from the open com port. Returns when the buffer is
+filled, the numer of requested linefeeds has been received or the timeout
+period has passed. The bootloaders may send 0x0d,0x0a,0x0a or 0x0d,0x0a as
+linefeed pattern
+2013-06-28 Torsten Lang
+Note: We *could* filter out surplus 0x0a characters like in <CR><LF><LF>
+but as we don't know how the individual bootloader behaves we don't want
+to wait for possible surplus <LF> (which would slow down the transfer).
+Thus, we just terminate after the expected number of <CR><LF> sequences
+and leave it to the command handler in lpcprog.c to filter out surplus
+<LF> characters which then occur as leading character in answers or
+echoed commands.
+\param [in] ISPEnvironment.
+\param [out] Answer buffer to hold the bytes read from the serial port.
+\param [in] MaxSize the size of buffer pointed to by Answer.
+\param [out] RealSize pointer to a long that returns the amout of the
+buffer that is actually used.
+\param [in] WantedNr0x0A the maximum number of linefeeds to accept before
+returning.
+\param [in] timeOutMilliseconds the maximum amount of time to wait before
+reading with an incomplete buffer.
+*/
+void ReceiveComPort(ISP_ENVIRONMENT *IspEnvironment,
+                                    const char *Ans, unsigned long MaxSize,
+                                    unsigned long *RealSize, unsigned long WantedNr0x0A,
+                                    unsigned timeOutMilliseconds)
+{
+    unsigned long tmp_realsize;
+    unsigned long nr_of_0x0A = 0;
+    unsigned long nr_of_0x0D = 0;
+    int eof = 0;
+    unsigned long p;
+    unsigned char *Answer;
+    unsigned char *endPtr;
+    char tmp_string[32];
+    static char residual_data[128] = {'\0'};
+    int lf = 0;
+
+    Answer  = (unsigned char*) Ans;
+
+    SerialTimeoutSet(IspEnvironment, timeOutMilliseconds);
+
+    *RealSize = 0;
+    endPtr = NULL;
+
+    do
+    {
+        if (residual_data[0] == '\0')
+        {
+            /* Receive new data */
+            ReceiveComPortBlock(IspEnvironment, Answer + (*RealSize), MaxSize - 1 - (*RealSize), &tmp_realsize);
+        }
+        else
+        {
+            /* Take over any old residual data */
+            strcpy((char *)Answer, residual_data);
+            tmp_realsize = strlen((char *)Answer);
+            residual_data[0] = '\0';
+        }
+
+        if (tmp_realsize != 0)
+        {
+            for (p = (*RealSize); p < (*RealSize) + tmp_realsize; p++)
+            {
+                /* Torsten Lang 2013-05-06 Scan for 0x0d,0x0a,0x0a and 0x0d,0x0a as linefeed pattern */
+                if (Answer[p] == 0x0a)
+                {
+                    if (lf != 0)
+                    {
+                        nr_of_0x0A++;
+                        lf = 0;
+                        if (nr_of_0x0A >= WantedNr0x0A)
+                        {
+                            endPtr = &Answer[p+1];
+                        }
+                    }
+                }
+                else if (Answer[p] == 0x0d)
+                {
+                    nr_of_0x0D++;
+                    lf = 1;
+                }
+                else if (((signed char) Answer[p]) < 0)
+                {
+                    eof = 1;
+                    lf  = 0;
+                }
+                else if (lf != 0)
+                {
+                    nr_of_0x0D++;
+                    nr_of_0x0A++;
+                    lf = 0;
+                    if (nr_of_0x0A >= WantedNr0x0A)
+                    {
+                        endPtr = &Answer[p+1];
+                    }
+                }
+            }
+            (*RealSize) += tmp_realsize;
+        }
+    } while (((*RealSize) < MaxSize) && (SerialTimeoutCheck(IspEnvironment) == 0) && (nr_of_0x0A < WantedNr0x0A) && !eof);
+
+    /* Torsten Lang 2013-05-06 Store residual data and cut answer after expected nr. of 0x0a */
+    Answer[*RealSize] = '\0';
+    if (endPtr != NULL)
+    {
+        strcpy(residual_data, (char *)endPtr);
+        *endPtr = '\0';
+        /* Torsten Lang 2013-06-28 Update size info */
+        *RealSize = endPtr-Answer;
+    }
+
+    sprintf(tmp_string, "Answer(Length=%ld): ", (*RealSize));
+    DumpString(3, Answer, (*RealSize), tmp_string);
+}
+
+
+#if !defined COMPILE_FOR_LPC21
+
+/***************************** ReceiveComPortBlockComplete **************/
+/**  Receives a fixed block from the open com port. Returns when the
+block is completely filled or the timeout period has passed
+\param [out] block buffer to hold the bytes read from the serial port.
+\param [in] size the size of the buffer pointed to by block.
+\param [in] timeOut the maximum amount of time to wait before guvung up on
+completing the read.
+\return 0 if successful, non-zero otherwise.
+*/
+int ReceiveComPortBlockComplete(ISP_ENVIRONMENT *IspEnvironment,
+                                                    void *block, size_t size, unsigned timeout)
+{
+    unsigned long realsize = 0, read;
+    char *result;
+    char tmp_string[32];
+
+    result = (char*) block;
+
+    SerialTimeoutSet(IspEnvironment, timeout);
+
+    do
+    {
+        ReceiveComPortBlock(IspEnvironment, result + realsize, size - realsize, &read);
+
+        realsize += read;
+
+    } while ((realsize < size) && (SerialTimeoutCheck(IspEnvironment) == 0));
+
+    sprintf(tmp_string, "Answer(Length=%ld): ", realsize);
+    DumpString(3, result, realsize, tmp_string);
+
+    if (realsize != size)
+    {
+        return 1;
+    }
+    return 0;
+}
+
+/***************************** ReadArguments ****************************/
+/**  Reads the command line arguments and parses it for the various
+options. Uses the same arguments as main.  Used to separate the command
+line parsing from main and improve its readability.  This should also make
+it easier to modify the command line parsing in the future.
+\param [in] argc the number of arguments.
+\param [in] argv an array of pointers to the arguments.
+*/
+static void ReadArguments(ISP_ENVIRONMENT *IspEnvironment, unsigned int argc, char *argv[])
+{
+    unsigned int i;
+
+    if (argc >= 5)
+    {
+        for (i = 1; i < argc - 3; i++)
+        {
+            if (stricmp(argv[i], "-wipe") == 0)
+            {
+                IspEnvironment->WipeDevice = 1;
+                DebugPrintf(3, "Wipe entire device before writing.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-bin") == 0)
+            {
+                IspEnvironment->FileFormat = FORMAT_BINARY;
+                DebugPrintf(3, "Binary format file input.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-hex") == 0)
+            {
+                IspEnvironment->FileFormat = FORMAT_HEX;
+                DebugPrintf(3, "Hex format file input.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-logfile") == 0)
+            {
+                IspEnvironment->LogFile = 1;
+                DebugPrintf(3, "Log terminal output.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-detectonly") == 0)
+            {
+                IspEnvironment->DetectOnly  = 1;
+                IspEnvironment->ProgramChip = 0;
+                DebugPrintf(3, "Only detect LPC chip part id.\n");
+                continue;
+            }
+
+            if(strnicmp(argv[i],"-debug", 6) == 0)
+            {
+                char* num;
+                num = argv[i] + 6;
+                while(*num && isdigit(*num) == 0) num++;
+                if(isdigit(*num) != 0) debug_level = atoi( num);
+                else debug_level = 4;
+                DebugPrintf(3, "Turn on debug, level: %d.\n", debug_level);
+                continue;
+            }
+
+            if (stricmp(argv[i], "-boothold") == 0)
+            {
+                IspEnvironment->BootHold = 1;
+                DebugPrintf(3, "hold EnableBootLoader asserted throughout programming sequence.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-donotstart") == 0)
+            {
+                IspEnvironment->DoNotStart = 1;
+                DebugPrintf(3, "Do NOT start MCU after programming.\n");
+                continue;
+            }
+
+            if(strnicmp(argv[i],"-try", 4) == 0)
+            {
+                int
+                    retry;
+                retry=atoi(&argv[i][4]);
+                if(retry>0)
+                {
+                    IspEnvironment->nQuestionMarks=retry;
+                    DebugPrintf(3, "Retry count: %d.\n", IspEnvironment->nQuestionMarks);
+                }
+                else
+                {
+                    fprintf(stderr,"invalid argument for -try: \"%s\"\n",argv[i]);
+                }
+                continue;
+            }
+
+
+            if (stricmp(argv[i], "-control") == 0)
+            {
+                IspEnvironment->ControlLines = 1;
+                DebugPrintf(3, "Use RTS/DTR to control target state.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-controlswap") == 0)
+            {
+                IspEnvironment->ControlLinesSwapped = 1;
+                DebugPrintf(3, "Use RTS to control reset, and DTR to control P0.14(ISP).\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-controlinv") == 0)
+            {
+                IspEnvironment->ControlLinesInverted = 1;
+                DebugPrintf(3, "Invert state of RTS & DTR (0=true/assert/set, 1=false/deassert/clear).\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-halfduplex") == 0)
+            {
+                IspEnvironment->HalfDuplex = 1;
+                DebugPrintf(3, "halfduplex serial communication.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-ADARM") == 0)
+            {
+                IspEnvironment->micro = ANALOG_DEVICES_ARM;
+                DebugPrintf(2, "Target: Analog Devices.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-NXPARM") == 0 || stricmp(argv[i], "-PHILIPSARM") == 0)
+            {
+                IspEnvironment->micro = NXP_ARM;
+                DebugPrintf(2, "Target: NXP.\n");
+                continue;
+            }
+
+            if (stricmp(argv[i], "-Verify") == 0)
+            {
+                IspEnvironment->Verify = 1;
+                DebugPrintf(2, "Verify after copy RAM to Flash.\n");
+                continue;
+            }
+
+#ifdef INTEGRATED_IN_WIN_APP
+            if (stricmp(argv[i], "-nosync") == 0)
+            {
+                IspEnvironment->NoSync = 1;
+                DebugPrintf(2, "Performing no syncing, already done.\n");
+                continue;
+            }
+#endif
+
+#ifdef TERMINAL_SUPPORT
+            if (CheckTerminalParameters(IspEnvironment, argv[i]))
+            {
+                continue;
+            }
+#endif
+
+            if(*argv[i] == '-') DebugPrintf( 2, "Unknown command line option: \"%s\"\n", argv[i]);
+            else
+            {
+                int ret_val;
+                if(IspEnvironment->FileFormat == FORMAT_HEX)
+                {
+                    ret_val = AddFileHex(IspEnvironment, argv[i]);
+                }
+                else
+                {
+                    ret_val = AddFileBinary(IspEnvironment, argv[i]);
+                }
+                if( ret_val != 0)
+                {
+                    DebugPrintf( 2, "Unknown command line option: \"%s\"\n", argv[i]);
+                }
+            }
+        }
+
+        // Newest cygwin delivers a '\x0d' at the end of argument
+        // when calling lpc21isp from batch file
+        for (i = 0; i < strlen(argv[argc - 1]) && i < (sizeof(IspEnvironment->StringOscillator) - 1) &&
+            argv[argc - 1][i] >= '0' && argv[argc - 1][i] <= '9'; i++)
+        {
+            IspEnvironment->StringOscillator[i] = argv[argc - 1][i];
+        }
+        IspEnvironment->StringOscillator[i] = 0;
+
+        IspEnvironment->serial_port = argv[argc - 3];
+        IspEnvironment->baud_rate = argv[argc - 2];
+    }
+
+    if (argc < 5)
+    {
+        debug_level = (debug_level < 2) ? 2 : debug_level;
+    }
+
+    if (argc < 5)
+    {
+        DebugPrintf(2, "\n"
+                       "Portable command line ISP\n"
+                       "for NXP LPC family and Analog Devices ADUC 70xx\n"
+                       "Version " VERSION_STR " compiled for " COMPILED_FOR ": " __DATE__ ", " __TIME__ "\n"
+                       "Copyright (c) by Martin Maurer, 2003-2013, Email: Martin.Maurer@clibb.de\n"
+                       "Portions Copyright (c) by Aeolus Development 2004, www.aeolusdevelopment.com\n"
+                       "\n");
+
+        DebugPrintf(1, "Syntax:  lpc21isp [Options] file[ file[ ...]] comport baudrate Oscillator_in_kHz\n\n"
+                       "Example: lpc21isp test.hex com1 115200 14746\n\n"
+                       "Options: -bin         for uploading binary file\n"
+                       "         -hex         for uploading file in intel hex format (default)\n"
+                       "         -term        for starting terminal after upload\n"
+                       "         -termonly    for starting terminal without an upload\n"
+                       "         -localecho   for local echo in terminal\n"
+                       "         -detectonly  detect only used LPC chiptype (NXPARM only)\n"
+                       "         -debug0      for no debug\n"
+                       "         -debug3      for progress info only\n"
+                       "         -debug5      for full debug\n"
+                       "         -donotstart  do not start MCU after download\n"
+                       "         -try<n>      try n times to synchronise\n"
+                       "         -wipe        Erase entire device before upload\n"
+                       "         -control     for controlling RS232 lines for easier booting\n"
+                       "                      (Reset = DTR, EnableBootLoader = RTS)\n"
+                       "         -boothold    hold EnableBootLoader asserted throughout sequence\n"
+#ifdef INTEGRATED_IN_WIN_APP
+                       "         -nosync      Do not synchronize device via '?'\n"
+#endif
+                       "         -controlswap swap RS232 control lines\n"
+                       "                      (Reset = RTS, EnableBootLoader = DTR)\n"
+                       "         -controlinv  Invert state of RTS & DTR \n"
+                       "                      (0=true/assert/set, 1=false/deassert/clear).\n"
+                       "         -verify      Verify the data in Flash after every writes to\n"
+                       "                      sector. To detect errors in writing to Flash ROM\n"
+                       "         -logfile     for enabling logging of terminal output to lpc21isp.log\n"
+                       "         -halfduplex  use halfduplex serial communication (i.e. with K-Line)\n"
+                       "         -ADARM       for downloading to an Analog Devices\n"
+                       "                      ARM microcontroller ADUC70xx\n"
+                       "         -NXPARM      for downloading to a chip of NXP LPC family (default)\n");
+
+        exit(1);
+    }
+
+    if (IspEnvironment->micro == NXP_ARM)
+    {
+        // If StringOscillator is bigger than 100 MHz, there seems to be something wrong
+        if (strlen(IspEnvironment->StringOscillator) > 5)
+        {
+            DebugPrintf(1, "Invalid crystal frequency %s\n", IspEnvironment->StringOscillator);
+            exit(1);
+        }
+    }
+}
+
+/***************************** ResetTarget ******************************/
+/**  Resets the target leaving it in either download (program) mode or
+run mode.
+\param [in] mode the mode to leave the target in.
+*/
+void ResetTarget(ISP_ENVIRONMENT *IspEnvironment, TARGET_MODE mode)
+{
+#if defined(__linux__) && defined(GPIO_RST) && defined(GPIO_ISP)
+
+// This code section allows using Linux GPIO pins to control the -RST and -ISP
+// signals of the target microcontroller.
+//
+// Build lpc21isp to use Linux GPIO like this:
+//
+// make CFLAGS="-Wall -DGPIO_ISP=23 -DGPIO_RST=18"
+//
+// The GPIO pins must be pre-configured in /etc/rc.local (or other startup script)
+// similar to the following:
+//
+// # Configure -ISP signal
+// echo 23 >/sys/class/gpio/export
+// echo out >/sys/class/gpio/gpio23/direction
+// echo 1 >/sys/class/gpio/gpio23/value
+// chown root.gpio /sys/class/gpio/gpio23/value
+// chmod 660 /sys/class/gpio/gpio23/value
+//
+// # Configure -RST signal
+// echo 18 >/sys/class/gpio/export
+// echo out >/sys/class/gpio/gpio18/direction
+// echo 1 >/sys/class/gpio/gpio18/value
+// chown root.gpio /sys/class/gpio/gpio18/value
+// chmod 660 /sys/class/gpio/gpio18/value
+//
+// Then if the user is a member of the gpio group, lpc21isp will not requre any
+// special permissions to access the GPIO signals.
+
+  char gpio_isp_filename[256];
+  char gpio_rst_filename[256];
+  int gpio_isp;
+  int gpio_rst;
+
+  memset(gpio_isp_filename, 0, sizeof(gpio_isp_filename));
+  sprintf(gpio_isp_filename, "/sys/class/gpio/gpio%d/value", GPIO_ISP);
+
+  memset(gpio_rst_filename, 0, sizeof(gpio_rst_filename));
+  sprintf(gpio_rst_filename, "/sys/class/gpio/gpio%d/value", GPIO_RST);
+
+  gpio_isp = open(gpio_isp_filename, O_WRONLY);
+  if (gpio_isp < 0)
+  {
+    fprintf(stderr, "ERROR: open() for %s failed, %s\n", gpio_isp_filename, strerror(errno));
+    exit(1);
+  }
+
+  gpio_rst = open(gpio_rst_filename, O_WRONLY);
+  if (gpio_rst < 0)
+  {
+    fprintf(stderr, "ERROR: open() for %s failed, %s\n", gpio_rst_filename, strerror(errno));
+    exit(1);
+  }
+
+  switch (mode)
+  {
+    case PROGRAM_MODE :
+      write(gpio_isp, "0\n", 2);  // Assert -ISP
+      Sleep(100);
+      write(gpio_rst, "0\n", 2);  // Assert -RST
+      Sleep(500);
+      write(gpio_rst, "1\n", 2);  // Deassert -RST
+      Sleep(100);
+      write(gpio_isp, "1\n", 2);  // Deassert -ISP
+      Sleep(100);
+      break;;
+
+    case RUN_MODE :
+      write(gpio_rst, "0\n", 2);  // Assert -RST
+      Sleep(500);
+      write(gpio_rst, "1\n", 2);  // Deassert -ISP
+      Sleep(100);
+      break;;
+  }
+
+  close(gpio_isp);
+  close(gpio_rst);
+
+  return;
+#endif
+
+    if (IspEnvironment->ControlLines)
+    {
+        switch (mode)
+        {
+        /* Reset and jump to boot loader.                       */
+        case PROGRAM_MODE:
+            ControlModemLines(IspEnvironment, 1, 1);
+            Sleep(100);
+            ClearSerialPortBuffers(IspEnvironment);
+            Sleep(100);
+            ControlModemLines(IspEnvironment, 0, 1);
+            //Longer delay is the Reset signal is conected to an external rest controller
+            Sleep(500);
+            // Clear the RTS line after having reset the micro
+            // Needed for the "GO <Address> <Mode>" ISP command to work */
+            if(!IspEnvironment->BootHold)
+            {
+                ControlModemLines(IspEnvironment, 0, 0);
+            }
+            break;
+
+        /* Reset and start uploaded program                     */
+        case RUN_MODE:
+            ControlModemLines(IspEnvironment, 1, 0);
+            Sleep(100);
+            ClearSerialPortBuffers(IspEnvironment);
+            Sleep(100);
+            ControlModemLines(IspEnvironment, 0, 0);
+            Sleep(100);
+            break;
+        }
+    }
+}
+
+
+/***************************** Ascii2Hex ********************************/
+/**  Converts a hex character to its equivalent number value. In case of an
+error rather abruptly terminates the program.
+\param [in] c the hex digit to convert.
+\return the value of the hex digit.
+*/
+static unsigned char Ascii2Hex(unsigned char c)
+{
+    if (c >= '0' && c <= '9')
+    {
+        return (unsigned char)(c - '0');
+    }
+
+    if (c >= 'A' && c <= 'F')
+    {
+        return (unsigned char)(c - 'A' + 10);
+    }
+
+    if (c >= 'a' && c <= 'f')
+    {
+        return (unsigned char)(c - 'a' + 10);
+    }
+
+    DebugPrintf(1, "Wrong Hex-Nibble %c (%02X)\n", c, c);
+    exit(1);
+
+    return 0;  // this "return" will never be reached, but some compilers give a warning if it is not present
+}
+
+
+/***************************** AddFileHex *******************************/
+/**  Add a file to the list of files to read in, flag it as hex format.
+\param [in] IspEnvironment Programming environment.
+\param [in] arg The argument that was passed to the program as a file name.
+\return 0 on success, an error code otherwise.
+*/
+static int AddFileHex(ISP_ENVIRONMENT *IspEnvironment, const char *arg)
+{
+    FILE_LIST *entry;
+
+    // Add file to list.  If cannot allocate storage for node return an error.
+    entry = malloc(sizeof(FILE_LIST));
+    if( entry == 0)
+    {
+        DebugPrintf(1, "Error %d Could not allocated memory for file node %s\n", ERR_ALLOC_FILE_LIST, arg);
+        return  ERR_ALLOC_FILE_LIST;
+    }
+
+    // Build up entry and insert it at the start of the list.
+    entry->name = arg;
+    entry->prev = IspEnvironment->f_list;
+    entry->hex_flag = 1;
+    IspEnvironment->f_list = entry;
+
+    return 0;       // Success.
+}
+
+
+/***************************** AddFileBinary ****************************/
+/**  Add a file to the list of files to read in, flag it as binary format.
+\param [in] IspEnvironment Programming environment.
+\param [in] arg The argument that was passed to the program as a file name.
+\return 0 on success, an error code otherwise.
+*/
+static int AddFileBinary(ISP_ENVIRONMENT *IspEnvironment, const char *arg)
+{
+    FILE_LIST *entry;
+
+    // Add file to list. If cannot allocate storage for node return an error.
+    entry = malloc(sizeof(FILE_LIST));
+    if( entry == 0)
+    {
+        DebugPrintf( 1, "Error %d Could not allocated memory for file node %s\n", ERR_ALLOC_FILE_LIST, arg);
+        return  ERR_ALLOC_FILE_LIST;
+    }
+
+    // Build up entry and insert it at the start of the list.
+    entry->name = arg;
+    entry->prev = IspEnvironment->f_list;
+    entry->hex_flag = 0;
+    IspEnvironment->f_list = entry;
+
+    return 0;       // Success.
+}
+
+#if 0
+void ReadHexFile(ISP_ENVIRONMENT *IspEnvironment)
+{
+    LoadFile(IspEnvironment);
+
+    if (IspEnvironment->BinaryLength)
+    {
+        BINARY* FileContent = IspEnvironment->FileContent;
+
+        unsigned long  Pos;
+        unsigned char  RecordLength;
+        unsigned short RecordAddress;
+        unsigned long  RealAddress = 0;
+        unsigned char  RecordType;
+        unsigned char  Hexvalue;
+        unsigned long  StartAddress;
+        int            BinaryOffsetDefined = 0;
+        unsigned char  i;
+
+
+        DebugPrintf(3, "Converting file %s to binary format...\n", IspEnvironment->input_file);
+
+        Pos = 0;
+        while (Pos < IspEnvironment->BinaryLength)
+        {
+            if (FileContent[Pos] == '\r')
+            {
+                Pos++;
+                continue;
+            }
+
+            if (FileContent[Pos] == '\n')
+            {
+                Pos++;
+                continue;
+            }
+
+            if (FileContent[Pos] != ':')
+            {
+                DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
+                exit(1);
+            }
+
+            Pos++;
+
+            RecordLength   = Ascii2Hex(FileContent[Pos++]);
+            RecordLength <<= 4;
+            RecordLength  |= Ascii2Hex(FileContent[Pos++]);
+
+            DebugPrintf(4, "RecordLength = %02X\n", RecordLength);
+
+            RecordAddress   = Ascii2Hex(FileContent[Pos++]);
+            RecordAddress <<= 4;
+            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
+            RecordAddress <<= 4;
+            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
+            RecordAddress <<= 4;
+            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
+
+            DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);
+
+            RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;
+
+            DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);
+
+            RecordType      = Ascii2Hex(FileContent[Pos++]);
+            RecordType    <<= 4;
+            RecordType     |= Ascii2Hex(FileContent[Pos++]);
+
+            DebugPrintf(4, "RecordType = %02X\n", RecordType);
+
+            if (RecordType == 0x00)          // 00 - Data record
+            {
+                /*
+                * Binary Offset is defined as soon as first data record read
+                */
+
+                //BinaryOffsetDefined = 1;
+
+                // Memory for binary file big enough ?
+                while ((RealAddress + RecordLength - IspEnvironment->BinaryOffset) > IspEnvironment->BinaryMemSize)
+                {
+                    IspEnvironment->BinaryMemSize <<= 1;    // Double the size allocated !!!
+                    IspEnvironment->BinaryContent = (BINARY*) realloc(IspEnvironment->BinaryContent, IspEnvironment->BinaryMemSize);
+                }
+
+                // We need to know, what the highest address is,
+                // how many bytes / sectors we must flash
+                if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
+                {
+                    IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
+                    DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
+                }
+
+                for (i = 0; i < RecordLength; i++)
+                {
+                    Hexvalue        = Ascii2Hex(FileContent[Pos++]);
+                    Hexvalue      <<= 4;
+                    Hexvalue       |= Ascii2Hex(FileContent[Pos++]);
+                    IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
+                }
+            }
+            else if (RecordType == 0x01)     // 01 - End of file record
+            {
+                break;
+            }
+            else if (RecordType == 0x02)     // 02 - Extended segment address record
+            {
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    RealAddress <<= 4;
+                    if (i == 0)
+                    {
+                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                RealAddress <<= 4;
+            }
+            else if (RecordType == 0x03)     // 03 - Start segment address record
+            {
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    RealAddress <<= 4;
+                    if (i == 0)
+                    {
+                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                RealAddress <<= 8;
+            }
+            else if (RecordType == 0x04)     // 04 - Extended linear address record, used by IAR
+            {
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    RealAddress <<= 4;
+                    if (i == 0)
+                    {
+                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                RealAddress <<= 16;
+                if (!BinaryOffsetDefined)
+                {
+                    // set startaddress of BinaryContent
+                    // use of LPC_FLASHMASK to allow a memory range, not taking the first
+                    // [04] record as actual start-address.
+                    IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
+                }
+                else
+                {
+                    if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
+                    {
+                        DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n"
+                                       "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
+                                       IspEnvironment->BinaryOffset, RealAddress);
+                        exit(1);
+                    }
+                }
+            }
+            else if (RecordType == 0x05)     // 05 - Start linear address record
+            {
+                StartAddress = 0;
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    StartAddress <<= 4;
+                    if (i == 0)
+                    {
+                        StartAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        StartAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
+                IspEnvironment->StartAddress = StartAddress;
+            }
+
+            while (FileContent[Pos++] != 0x0a)      // Search till line end
+            {
+            }
+        }
+
+        DebugPrintf(2, "\tconverted to binary format...\n");
+
+        // When debugging is switched on, output result of conversion to file debugout.bin
+        if (debug_level >= 4)
+        {
+            int fdout;
+            fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
+            write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
+            close(fdout);
+        }
+    }
+}
+#endif // #if 0
+
+
+/***************************** LoadFile *********************************/
+/**  Loads the requested file to download into memory.
+\param [in] IspEnvironment  structure containing input filename
+\param [in] filename  the name of the file to read in.
+\param [in] FileFormat  the format of the file to read in (FORMAT_HEX or FORMAT_BINARY)
+\return 0 if successful, otherwise an error code.
+*/
+static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat)
+{
+    int            fd;
+    int            i;
+    int            BinaryOffsetDefined;
+    unsigned long  Pos;
+    unsigned long  FileLength;
+    BINARY        *FileContent;              /**< Used to store the content of a hex */
+                                             /*   file before converting to binary.  */
+    unsigned long  BinaryMemSize;
+
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if (fd == -1)
+    {
+        DebugPrintf(1, "Can't open file %s\n", filename);
+        return ERR_FILE_OPEN_HEX;
+    }
+
+    FileLength = lseek(fd, 0L, 2);      // Get file size
+
+    if (FileLength == (size_t)-1)
+    {
+        DebugPrintf(1, "\nFileLength = -1 !?!\n");
+        return ERR_FILE_SIZE_HEX;
+    }
+
+    lseek(fd, 0L, 0);
+
+    // Just read the entire file into memory to parse.
+    FileContent = (BINARY*) malloc(FileLength);
+
+    if( FileContent == 0)
+    {
+        DebugPrintf( 1, "\nCouldn't allocate enough memory for file.\n");
+        return ERR_FILE_ALLOC_HEX;
+    }
+
+    BinaryOffsetDefined = 0;
+
+    BinaryMemSize = IspEnvironment->BinaryLength;
+
+    read(fd, FileContent, FileLength);
+
+    close(fd);
+
+    DebugPrintf(2, "File %s:\n\tloaded...\n", filename);
+
+    // Intel-Hex -> Binary Conversion
+
+    if (FileFormat == FORMAT_HEX)
+    {
+        unsigned char  RecordLength;
+        unsigned short RecordAddress;
+        unsigned long  RealAddress = 0;
+        unsigned char  RecordType;
+        unsigned char  Hexvalue;
+        unsigned long  StartAddress;
+
+        DebugPrintf(3, "Converting file %s to binary format...\n", filename);
+
+        Pos = 0;
+        while (Pos < FileLength)
+        {
+            if (FileContent[Pos] == '\r')
+            {
+                Pos++;
+                continue;
+            }
+
+            if (FileContent[Pos] == '\n')
+            {
+                Pos++;
+                continue;
+            }
+
+            if (FileContent[Pos] != ':')
+            {
+                DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
+                exit(1);
+            }
+
+            Pos++;
+
+            RecordLength   = Ascii2Hex(FileContent[Pos++]);
+            RecordLength <<= 4;
+            RecordLength  |= Ascii2Hex(FileContent[Pos++]);
+
+            DebugPrintf(4, "RecordLength = %02X\n", RecordLength);
+
+            RecordAddress   = Ascii2Hex(FileContent[Pos++]);
+            RecordAddress <<= 4;
+            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
+            RecordAddress <<= 4;
+            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
+            RecordAddress <<= 4;
+            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
+
+            DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);
+
+            RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;
+
+            DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);
+
+            RecordType      = Ascii2Hex(FileContent[Pos++]);
+            RecordType    <<= 4;
+            RecordType     |= Ascii2Hex(FileContent[Pos++]);
+
+            DebugPrintf(4, "RecordType = %02X\n", RecordType);
+
+            if (RecordType == 0x00)          // 00 - Data record
+            {
+                /*
+                * Binary Offset is defined as soon as first data record read
+                */
+                BinaryOffsetDefined = 1;
+                // Memory for binary file big enough ?
+                while (RealAddress + RecordLength - IspEnvironment->BinaryOffset > BinaryMemSize)
+                {
+                    if(!BinaryMemSize) BinaryMemSize = FileLength * 2;
+                    else BinaryMemSize <<= 1;
+                    IspEnvironment->BinaryContent = realloc(IspEnvironment->BinaryContent, BinaryMemSize);
+                }
+
+                // We need to know, what the highest address is,
+                // how many bytes / sectors we must flash
+                if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
+                {
+                    IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
+                    DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
+                }
+
+                for (i = 0; i < RecordLength; i++)
+                {
+                    Hexvalue        = Ascii2Hex(FileContent[Pos++]);
+                    Hexvalue      <<= 4;
+                    Hexvalue       |= Ascii2Hex(FileContent[Pos++]);
+                    IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
+                }
+            }
+            else if (RecordType == 0x01)     // 01 - End of file record
+            {
+                break;
+            }
+            else if (RecordType == 0x02)     // 02 - Extended segment address record
+            {
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    RealAddress <<= 4;
+                    if (i == 0)
+                    {
+                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                RealAddress <<= 4;
+            }
+            else if (RecordType == 0x03)     // 03 - Start segment address record
+            {
+                unsigned long cs,ip;
+                StartAddress = 0;
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    StartAddress <<= 4;
+                    if (i == 0)
+                    {
+                        StartAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        StartAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                cs = StartAddress >> 16; //high part
+                ip = StartAddress & 0xffff; //low part
+                StartAddress = cs*16+ip; //segmented 20-bit space
+                DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
+                IspEnvironment->StartAddress = StartAddress;
+            }
+            else if (RecordType == 0x04)     // 04 - Extended linear address record, used by IAR
+            {
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    RealAddress <<= 4;
+                    if (i == 0)
+                    {
+                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                RealAddress <<= 16;
+                if (!BinaryOffsetDefined)
+                {
+                    // set startaddress of BinaryContent
+                    // use of LPC_FLASHMASK to allow a memory range, not taking the first
+                    // [04] record as actual start-address.
+                    IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
+                }
+                else
+                {
+                    if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
+                    {
+                        DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n");
+                        DebugPrintf(1, "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
+                            IspEnvironment->BinaryOffset, RealAddress);
+                        return ERR_MEMORY_RANGE;
+                    }
+                }
+            }
+            else if (RecordType == 0x05)     // 05 - Start linear address record
+            {
+                StartAddress = 0;
+                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
+                {
+                    StartAddress <<= 4;
+                    if (i == 0)
+                    {
+                        StartAddress  = Ascii2Hex(FileContent[Pos++]);
+                    }
+                    else
+                    {
+                        StartAddress |= Ascii2Hex(FileContent[Pos++]);
+                    }
+                }
+                DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
+                IspEnvironment->StartAddress = StartAddress;
+            }
+            else
+            {
+                free( FileContent);
+                DebugPrintf( 1, "Error %d RecordType %02X not yet implemented\n", ERR_RECORD_TYPE_LOADFILE, RecordType);
+                return( ERR_RECORD_TYPE_LOADFILE);
+            }
+
+            while (FileContent[Pos++] != 0x0a)      // Search till line end
+            {
+            }
+        }
+
+        DebugPrintf(2, "\tconverted to binary format...\n");
+
+        // When debugging is switched on, output result of conversion to file debugout.bin
+        if (debug_level >= 4)
+        {
+            int fdout;
+            fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
+            write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
+            close(fdout);
+        }
+
+        free( FileContent);   // Done with file contents
+    }
+    else // FORMAT_BINARY
+    {
+        IspEnvironment->BinaryContent = FileContent;
+        IspEnvironment->BinaryLength = FileLength;
+    }
+
+    DebugPrintf(2, "\timage size : %ld\n", IspEnvironment->BinaryLength);
+
+    return 0;
+}
+
+/***************************** LoadFiles1 ********************************/
+/**  Loads the requested files to download into memory.
+\param [in] IspEnvironment structure containing input filename(s).
+\param [in] file simple linked list of files to read
+\return 0 if successful, otherwise an error code.
+*/
+static int LoadFiles1(ISP_ENVIRONMENT *IspEnvironment, const FILE_LIST *file)
+{
+    int ret_val;
+
+    if( file->prev != 0)
+    {
+        DebugPrintf( 3, "Follow file list %s\n", file->name);
+
+        ret_val = LoadFiles1( IspEnvironment, file->prev);
+    if( ret_val != 0)
+    {
+      return ret_val;
+    }
+    }
+
+    DebugPrintf( 3, "Attempt to read File %s\n", file->name);
+    if(file->hex_flag != 0)
+    {
+        ret_val = LoadFile(IspEnvironment, file->name, FORMAT_HEX);
+    }
+    else
+    {
+    ret_val = LoadFile(IspEnvironment, file->name, FORMAT_BINARY);
+    }
+    if( ret_val != 0)
+    {
+    return ret_val;
+    }
+
+    return 0;
+}
+
+/***************************** LoadFiles ********************************/
+/**  Loads the requested files to download into memory.
+\param [in] IspEnvironment structure containing input filename(s).
+\param [in] file simple linked list of files to read
+\return 0 if successful, otherwise an error code.
+*/
+static int LoadFiles(ISP_ENVIRONMENT *IspEnvironment)
+{
+  int ret_val;
+
+    ret_val = LoadFiles1(IspEnvironment, IspEnvironment->f_list);
+    if( ret_val != 0)
+    {
+    exit(1); // return ret_val;
+    }
+
+  DebugPrintf( 2, "Image size : %ld\n", IspEnvironment->BinaryLength);
+
+    // check length to flash for correct alignment, can happen with broken ld-scripts
+    if (IspEnvironment->BinaryLength % 4 != 0)
+    {
+        unsigned long NewBinaryLength = ((IspEnvironment->BinaryLength + 3)/4) * 4;
+
+        DebugPrintf( 2, "Warning:  data not aligned to 32 bits, padded (length was %lX, now %lX)\n", IspEnvironment->BinaryLength, NewBinaryLength);
+
+        IspEnvironment->BinaryLength = NewBinaryLength;
+    }
+
+  // When debugging is switched on, output result of conversion to file debugout.bin
+    if(debug_level >= 4)
+    {
+         int fdout;
+     DebugPrintf( 1, "Dumping image file.\n");
+         fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
+         write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
+         close(fdout);
+    }
+    return 0;
+}
+#endif // !defined COMPILE_FOR_LPC21
+
+#ifndef COMPILE_FOR_LPC21
+int PerformActions(ISP_ENVIRONMENT *IspEnvironment)
+{
+    int downloadResult = -1;
+
+    DebugPrintf(2, "lpc21isp version " VERSION_STR "\n");
+
+    /* Download requested, read in the input file.                  */
+    if (IspEnvironment->ProgramChip)
+    {
+        LoadFiles(IspEnvironment);
+    }
+
+    OpenSerialPort(IspEnvironment);   /* Open the serial port to the microcontroller. */
+
+    ResetTarget(IspEnvironment, PROGRAM_MODE);
+
+    ClearSerialPortBuffers(IspEnvironment);
+
+    /* Perform the requested download.                              */
+    if (IspEnvironment->ProgramChip || IspEnvironment->DetectOnly)
+    {
+        switch (IspEnvironment->micro)
+        {
+#ifdef LPC_SUPPORT
+        case NXP_ARM:
+            downloadResult = NxpDownload(IspEnvironment);
+            break;
+#endif
+
+#ifdef AD_SUPPORT
+        case ANALOG_DEVICES_ARM:
+            downloadResult = AnalogDevicesDownload(IspEnvironment);
+            break;
+#endif
+        }
+
+        if (downloadResult != 0)
+        {
+            CloseSerialPort(IspEnvironment);
+            exit(downloadResult);
+        }
+    }
+
+    if (IspEnvironment->StartAddress == 0 || IspEnvironment->TerminalOnly)
+    {
+        /* Only reset target if startaddress = 0
+        * Otherwise stay with the running program as started in Download()
+        */
+        ResetTarget(IspEnvironment, RUN_MODE);
+    }
+
+    debug_level = 1;    /* From now on there is no more debug output !! */
+                                        /* Therefore switch it off...                   */
+
+#ifdef TERMINAL_SUPPORT
+    // Pass control to Terminal which will provide a terminal if one was asked for
+    // User asked for terminal emulation, provide a really dumb terminal.
+    Terminal(IspEnvironment);
+#endif
+
+    CloseSerialPort(IspEnvironment);  /*  All done, close the serial port to the      */
+
+    return 0;
+}
+#endif
+
+/***************************** main *************************************/
+/**  main. Everything starts from here.
+\param [in] argc the number of arguments.
+\param [in] argv an array of pointers to the arguments.
+*/
+
+#if !defined COMPILE_FOR_LPC21
+
+#if defined INTEGRATED_IN_WIN_APP
+int AppDoProgram(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+    ISP_ENVIRONMENT IspEnvironment;
+
+    // Initialize debug level
+    debug_level = 2;
+
+    // Initialize ISP Environment
+    memset(&IspEnvironment, 0, sizeof(IspEnvironment));       // Clear the IspEnviroment to a known value
+    IspEnvironment.micro       = NXP_ARM;                     // Default Micro
+    IspEnvironment.FileFormat  = FORMAT_HEX;                  // Default File Format
+    IspEnvironment.ProgramChip = TRUE;                        // Default to Programming the chip
+    IspEnvironment.nQuestionMarks = 100;
+    IspEnvironment.DoNotStart = 0;
+    IspEnvironment.BootHold = 0;
+    ReadArguments(&IspEnvironment, argc, argv);               // Read and parse the command line
+
+    return PerformActions(&IspEnvironment);                   // Do as requested !
+}
+
+#endif // !defined COMPILE_FOR_LPC21
+
+/***************************** DumpString ******************************/
+/**  Prints an area of memory to stdout. Converts non-printables to hex.
+\param [in] level the debug level of the block to be dumped.  If this is
+less than or equal to the current debug level than the dump will happen
+otherwise this just returns.
+\param [in] b pointer to an area of memory.
+\param [in] size the length of the memory block to print.
+\param [in] prefix string is a pointer to a prefix string.
+*/
+void DumpString(int level, const void *b, size_t size, const char *prefix_string)
+{
+    size_t i;
+    const char * s = (const char*) b;
+    unsigned char c;
+
+    DebugPrintf(level, prefix_string);
+
+    DebugPrintf(level, "'");
+    for (i = 0; i < size; i++)
+    {
+        c = s[i];
+        if (c >= 0x20 && c <= 0x7e) /*isprint?*/
+        {
+            DebugPrintf(level, "%c", c);
+        }
+        else
+        {
+            DebugPrintf(level, "(%02X)", c);
+        }
+    }
+    DebugPrintf(level, "'\n");
+}
+
diff --git a/host/app/lpc21lisp/lpc21isp.h b/host/app/lpc21lisp/lpc21isp.h
new file mode 100644 (file)
index 0000000..a7fffcb
--- /dev/null
@@ -0,0 +1,302 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          lsp21isp.h\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+// #define INTEGRATED_IN_WIN_APP\r
+\r
+#if defined(_WIN32) && !defined(__CYGWIN__)\r
+#define COMPILE_FOR_WINDOWS\r
+#define COMPILED_FOR "Windows"\r
+#elif defined(__CYGWIN__)\r
+#define COMPILE_FOR_CYGWIN\r
+#define COMPILED_FOR "Cygwin"\r
+#elif (defined(__arm__) || defined(__thumb__)) && !defined(__linux__)\r
+#define COMPILE_FOR_LPC21\r
+#define COMPILED_FOR "ARM"\r
+#define printf iprintf\r
+#elif defined(__APPLE__)\r
+#define COMPILE_FOR_LINUX\r
+#define COMPILED_FOR "Apple MacOS X"\r
+#elif defined(__FreeBSD__)\r
+#define COMPILE_FOR_LINUX\r
+#define COMPILED_FOR "FreeBSD"\r
+#elif defined(__OpenBSD__)\r
+#define COMPILE_FOR_LINUX\r
+#define COMPILED_FOR "OpenBSD"\r
+#else\r
+#define COMPILE_FOR_LINUX\r
+#define COMPILED_FOR "Linux"\r
+#endif\r
+\r
+// The Required features can be enabled / disabled here\r
+#define LPC_SUPPORT\r
+\r
+#ifndef COMPILE_FOR_LPC21\r
+#define AD_SUPPORT\r
+#define TERMINAL_SUPPORT\r
+#endif\r
+\r
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN\r
+#include <windows.h>\r
+#include <io.h>\r
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN\r
+\r
+#if defined COMPILE_FOR_WINDOWS\r
+#include <conio.h>\r
+//#define TRACE(x) OutputDebugString(x)\r
+#define TRACE(x) printf("%s",x)\r
+#endif // defined COMPILE_FOR_WINDOWS\r
+\r
+#if defined COMPILE_FOR_CYGWIN\r
+//#define TRACE(x) OutputDebugString(x)\r
+#define TRACE(x) printf("%s",x)\r
+#endif // defined COMPILE_FOR_WINDOWS\r
+\r
+#if defined COMPILE_FOR_LINUX\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <strings.h>\r
+#include <sys/ioctl.h>\r
+extern void Sleep(unsigned long MilliSeconds);\r
+#define TRACE(x) printf("%s",x)\r
+#endif // defined COMPILE_FOR_LINUX\r
+\r
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN\r
+#include <termios.h>\r
+#include <unistd.h>     // for read and return value of lseek\r
+#include <sys/time.h>   // for select_time\r
+extern int kbhit(void);\r
+extern int getch(void);\r
+extern struct termios keyboard_origtty;\r
+#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN\r
+\r
+#include <ctype.h>      // isdigit()\r
+#include <stdio.h>      // stdout\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#if defined (COMPILE_FOR_LINUX)\r
+#if defined(__OpenBSD__)\r
+#include <errno.h>\r
+#else\r
+#include <sys/errno.h>\r
+#endif\r
+#endif\r
+\r
+#if defined COMPILE_FOR_LPC21\r
+#include <stdlib.h>\r
+#include <string.h>\r
+//#include <lpc_ioctl.h>  // if using libc serial port communication\r
+#else\r
+#include <fcntl.h>\r
+#endif\r
+\r
+typedef enum\r
+{\r
+    NXP_ARM,\r
+    ANALOG_DEVICES_ARM\r
+} TARGET;\r
+\r
+typedef enum\r
+{\r
+    PROGRAM_MODE,\r
+    RUN_MODE\r
+} TARGET_MODE;\r
+\r
+typedef enum\r
+{\r
+    FORMAT_BINARY,\r
+    FORMAT_HEX\r
+} FILE_FORMAT_TYPE;\r
+\r
+typedef unsigned char BINARY;               // Data type used for microcontroller\r
+\r
+/** Used to create list of files to read in. */\r
+typedef struct file_list FILE_LIST;\r
+\r
+#define ERR_RECORD_TYPE_LOADFILE  55  /**< File record type not yet implemented. */\r
+#define ERR_ALLOC_FILE_LIST       60  /**< Error allocation file list. */\r
+#define ERR_FILE_OPEN_HEX         61  /**< Couldn't open hex file. */\r
+#define ERR_FILE_SIZE_HEX         62  /**< Unexpected hex file size. */\r
+#define ERR_FILE_ALLOC_HEX        63  /**< Couldn't allocate enough memory for hex file. */\r
+#define ERR_MEMORY_RANGE          69  /**< Out of memory range. */\r
+\r
+/** Structure used to build list of input files. */\r
+struct file_list\r
+{\r
+    const char *name;       /**< The name of the input file.   */\r
+    FILE_LIST *prev;        /**< The previous file name in the list.*/\r
+    char hex_flag;          /**< True if the input file is hex.        */\r
+};\r
+\r
+typedef struct\r
+{\r
+#if !defined COMPILE_FOR_LPC21\r
+    TARGET micro;                                // The type of micro that will be programmed.\r
+    FILE_FORMAT_TYPE FileFormat;\r
+    unsigned char ProgramChip;                // Normally set\r
+\r
+    unsigned char ControlLines;\r
+    unsigned char ControlLinesSwapped;\r
+    unsigned char ControlLinesInverted;\r
+    unsigned char LogFile;\r
+    FILE_LIST *f_list;                  // List of files to read in.\r
+    int nQuestionMarks; // how many times to try to synchronise\r
+    int DoNotStart;\r
+    int BootHold;\r
+    char *serial_port;                  // Name of the serial port to use to\r
+                                        // communicate with the microcontroller.\r
+                                        // Read from the command line.\r
+#endif // !defined COMPILE_FOR_LPC21\r
+\r
+    unsigned char TerminalOnly;         // Declared here for lazyness saves ifdef's\r
+#ifdef TERMINAL_SUPPORT\r
+    unsigned char TerminalAfterUpload;\r
+    unsigned char LocalEcho;\r
+#endif\r
+\r
+    unsigned char HalfDuplex;           // Only used for LPC Programming\r
+    unsigned char DetectOnly;\r
+    unsigned char WipeDevice;\r
+    unsigned char Verify;\r
+    int           DetectedDevice;       /* index in LPCtypes[] array */\r
+    char *baud_rate;                    /**< Baud rate to use on the serial\r
+                                           * port communicating with the\r
+                                           * microcontroller. Read from the\r
+                                           * command line.                        */\r
+\r
+    char StringOscillator[6];           /**< Holds representation of oscillator\r
+                                           * speed from the command line.         */\r
+\r
+    BINARY *FileContent;\r
+    BINARY *BinaryContent;              /**< Binary image of the                  */\r
+                                          /* microcontroller's memory.            */\r
+    unsigned long BinaryLength;\r
+    unsigned long BinaryOffset;\r
+    unsigned long StartAddress;\r
+    unsigned long BinaryMemSize;\r
+\r
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN\r
+    HANDLE hCom;\r
+#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN\r
+\r
+#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21\r
+    int fdCom;\r
+#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21\r
+\r
+#if defined COMPILE_FOR_LINUX\r
+    struct termios oldtio, newtio;\r
+#endif // defined COMPILE_FOR_LINUX\r
+\r
+#ifdef INTEGRATED_IN_WIN_APP\r
+    unsigned char NoSync;\r
+#endif\r
+\r
+#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN\r
+    unsigned long serial_timeout_count;   /**< Local used to track timeouts on serial port read. */\r
+#else\r
+    unsigned serial_timeout_count;   /**< Local used to track timeouts on serial port read. */\r
+#endif\r
+\r
+} ISP_ENVIRONMENT;\r
+\r
+#if defined COMPILE_FOR_LPC21\r
+\r
+#define DebugPrintf(in, ...)\r
+\r
+#else\r
+extern int debug_level;\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+\r
+#define DebugPrintf AppDebugPrintf\r
+void AppDebugPrintf(int level, const char *fmt, ...);\r
+\r
+#define exit(val)   AppException(val)\r
+void AppException(int exception_level);\r
+\r
+int AppDoProgram(int argc, char *argv[]);\r
+\r
+#define Exclude_kbhit 1\r
+int AppSyncing(int trials);\r
+void AppWritten(int size);\r
+\r
+#else\r
+void DebugPrintf(int level, const char *fmt, ...);\r
+//#define DebugPrintf(level, ...) if (level <= debug_level) { TRACE( __VA_ARGS__ ); }\r
+#endif\r
+\r
+void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment);\r
+void ControlXonXoffSerialPort(ISP_ENVIRONMENT *IspEnvironment, unsigned char XonXoff);\r
+\r
+#endif\r
+\r
+\r
+#if defined COMPILE_FOR_LINUX\r
+#define stricmp strcasecmp\r
+#define strnicmp strncasecmp\r
+#endif // defined COMPILE_FOR_LINUX\r
+\r
+#ifndef O_BINARY\r
+#define O_BINARY 0\r
+#endif // O_BINARY\r
+\r
+#ifndef DWORD\r
+#define DWORD unsigned long\r
+#endif // DWORD\r
+\r
+/*\r
+debug levels\r
+0 - very quiet          - Nothing gets printed at this level\r
+1 - quiet               - Only error messages should be printed\r
+2 - indicate progress   - Add progress messages\r
+3 - first level debug   - Major level tracing\r
+4 - second level debug  - Add detailed debugging\r
+5 - log comm's          - log serial I/O\r
+*/\r
+\r
+\r
+void ReceiveComPort(ISP_ENVIRONMENT *IspEnvironment,\r
+                    const char *Ans, unsigned long MaxSize,\r
+                    unsigned long *RealSize, unsigned long WantedNr0x0A,\r
+                    unsigned timeOutMilliseconds);\r
+void PrepareKeyboardTtySettings(void);\r
+void ResetKeyboardTtySettings(void);\r
+void ResetTarget(ISP_ENVIRONMENT *IspEnvironment, TARGET_MODE mode);\r
+\r
+void DumpString(int level, const void *s, size_t size, const char *prefix_string);\r
+void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s);\r
+void SendComPortBlock(ISP_ENVIRONMENT *IspEnvironment, const void *s, size_t n);\r
+int ReceiveComPortBlockComplete(ISP_ENVIRONMENT *IspEnvironment, void *block, size_t size, unsigned timeout);\r
+void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment);\r
+void ControlXonXoffSerialPort(ISP_ENVIRONMENT *IspEnvironment, unsigned char XonXoff);\r
+\r
diff --git a/host/app/lpc21lisp/lpcprog.c b/host/app/lpc21lisp/lpcprog.c
new file mode 100644 (file)
index 0000000..2077bd6
--- /dev/null
@@ -0,0 +1,1649 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          lpcprog.c\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+// This file is for the Actual Programming of the LPC Chips\r
+\r
+#if defined(_WIN32)\r
+#include "malloc.h"\r
+#if !defined __BORLANDC__\r
+#include "StdAfx.h"\r
+#endif\r
+#endif // defined(_WIN32)\r
+#include "lpc21isp.h"\r
+\r
+#ifdef LPC_SUPPORT\r
+#include "lpcprog.h"\r
+\r
+static const unsigned int SectorTable_210x[] =\r
+{\r
+    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+    8192, 8192, 8192, 8192, 8192, 8192, 8192\r
+};\r
+\r
+static const unsigned int SectorTable_2103[] =\r
+{\r
+    4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096\r
+};\r
+\r
+static const unsigned int SectorTable_2109[] =\r
+{\r
+    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
+};\r
+\r
+static const unsigned int SectorTable_211x[] =\r
+{\r
+    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+    8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+};\r
+\r
+static const unsigned int SectorTable_212x[] =\r
+{\r
+    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+    65536, 65536, 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
+};\r
+\r
+// Used for devices with 500K (LPC2138 and LPC2148) and\r
+// for devices with 504K (1 extra 4k block at the end)\r
+static const unsigned int SectorTable_213x[] =\r
+{\r
+     4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,\r
+    32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,\r
+    32768, 32768, 32768, 32768, 32768, 32768,  4096,  4096,\r
+     4096,  4096,  4096,  4096\r
+};\r
+\r
+// Used for LPC17xx devices\r
+static const unsigned int SectorTable_17xx[] =\r
+{\r
+     4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,\r
+     4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,\r
+    32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,\r
+    32768, 32768, 32768, 32768, 32768, 32768\r
+};\r
+\r
+// Used for LPC18xx devices\r
+static const unsigned int SectorTable_18xx[] =\r
+{\r
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,\r
+    65536, 65536, 65536, 65536, 65536, 65536, 65536\r
+};\r
+\r
+// Used for LPC43xx devices\r
+static const unsigned int SectorTable_43xx[] =\r
+{\r
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,\r
+    65536, 65536, 65536, 65536, 65536, 65536, 65536\r
+};\r
+\r
+// Used for LPC8xx devices\r
+static const unsigned int SectorTable_8xx[] =\r
+{\r
+     1024,  1024,  1024,  1024,  1024,  1024,  1024,  1024,\r
+     1024,  1024,  1024,  1024,  1024,  1024,  1024,  1024\r
+};\r
+\r
+static int unsigned SectorTable_RAM[]  = { 65000 };\r
+\r
+static LPC_DEVICE_TYPE LPCtypes[] =\r
+{\r
+   { 0, 0, 0, 0, 0, 0, 0, 0, 0, CHIP_VARIANT_NONE },  /* unknown */\r
+\r
+   // id,        id2,  use id2, name of product, flash size, ram size, total number of sector, max copy size, sector table, chip variant\r
+\r
+   { 0x00008100, 0x00000000, 0, "810M021FN8",     4,   1,  4,  256, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
+   { 0x00008110, 0x00000000, 0, "811M001FDH16",   8,   2,  8, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
+   { 0x00008120, 0x00000000, 0, "812M101FDH16",  16,   4, 16, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
+   { 0x00008121, 0x00000000, 0, "812M101FD20",   16,   4, 16, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
+   { 0x00008122, 0x00000000, 0, "812M101FDH20",  16,   4, 16, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
+\r
+   { 0x2500102B, 0x00000000, 0, "1102",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+   { 0x0A07102B, 0x00000000, 0, "1110.../002",    4,   1,  1, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1A07102B, 0x00000000, 0, "1110.../002",    4,   1,  1, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0A16D02B, 0x00000000, 0, "1111.../002",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1A16D02B, 0x00000000, 0, "1111.../002",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x041E502B, 0x00000000, 0, "1111.../101",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2516D02B, 0x00000000, 0, "1111.../102",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0416502B, 0x00000000, 0, "1111.../201",    8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2516902B, 0x00000000, 0, "1111.../202",    8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x042D502B, 0x00000000, 0, "1112.../101",   16,   2,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2524D02B, 0x00000000, 0, "1112.../102",   16,   2,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0A24902B, 0x00000000, 0, "1112.../102",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1A24902B, 0x00000000, 0, "1112.../102",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0425502B, 0x00000000, 0, "1112.../201",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2524902B, 0x00000000, 0, "1112.../202",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0434502B, 0x00000000, 0, "1113.../201",   24,   4,  6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2532902B, 0x00000000, 0, "1113.../202",   24,   4,  6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0434102B, 0x00000000, 0, "1113.../301",   24,   8,  6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2532102B, 0x00000000, 0, "1113.../302",   24,   8,  6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0A40902B, 0x00000000, 0, "1114.../102",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1A40902B, 0x00000000, 0, "1114.../102",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0444502B, 0x00000000, 0, "1114.../201",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2540902B, 0x00000000, 0, "1114.../202",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0444102B, 0x00000000, 0, "1114.../301",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x2540102B, 0x00000000, 0, "1114.../302",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+   { 0x00040042, 0x00000000, 0, "1114.../203",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x00040040, 0x00000000, 0, "1114.../303",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x00040060, 0x00000000, 0, "1114.../323",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x00040070, 0x00000000, 0, "1114.../333",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x00050080, 0x00000000, 0, "1115.../303",   64,   8, 16, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+   { 0x1421102B, 0x00000000, 0, "11C12.../301",  16,   8,  4, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1440102B, 0x00000000, 0, "11C14.../301",  32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1431102B, 0x00000000, 0, "11C22.../301",  16,   8,  4, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x1430102B, 0x00000000, 0, "11C24.../301",  32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+   { 0x0364002B, 0x00000000, 0, "1224.../101",   32,   8,  4, 2048, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0364202B, 0x00000000, 0, "1224.../121",   48,  12, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0365002B, 0x00000000, 0, "1225.../301",   64,  16, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0365202B, 0x00000000, 0, "1225.../321",   80,  20, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0366002B, 0x00000000, 0, "1226",          96,  24, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+   { 0x0367002B, 0x00000000, 0, "1227",         128,  32, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+   { 0x2C42502B, 0x00000000, 0, "1311",           8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+   { 0x1816902B, 0x00000000, 0, "1311/01",        8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+   { 0x2C40102B, 0x00000000, 0, "1313",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+   { 0x1830102B, 0x00000000, 0, "1313/01",       32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+   { 0x3D01402B, 0x00000000, 0, "1342",          16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+   { 0x3D00002B, 0x00000000, 0, "1343",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+\r
+   { 0x25001118, 0x00000000, 0, "1751",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x25001121, 0x00000000, 0, "1752",          64,  16, 16, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x25011722, 0x00000000, 0, "1754",         128,  32, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x25011723, 0x00000000, 0, "1756",         256,  32, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x25013F37, 0x00000000, 0, "1758",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x25113737, 0x00000000, 0, "1759",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x26011922, 0x00000000, 0, "1764",         128,  32, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x26013733, 0x00000000, 0, "1765",         256,  64, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x26013F33, 0x00000000, 0, "1766",         256,  64, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x26012837, 0x00000000, 0, "1767",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x26013F37, 0x00000000, 0, "1768",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x26113F37, 0x00000000, 0, "1769",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+\r
+   { 0x27011132, 0x00000000, 0, "1774",         128,  40, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x27191F43, 0x00000000, 0, "1776",         256,  80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x27193747, 0x00000000, 0, "1777",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x27193F47, 0x00000000, 0, "1778",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x281D1743, 0x00000000, 0, "1785",         256,  80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x281D1F43, 0x00000000, 0, "1786",         256,  80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x281D3747, 0x00000000, 0, "1787",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+   { 0x281D3F47, 0x00000000, 0, "1788",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+\r
+   // LPC18xx\r
+   { 0xF00B1B3F, 0x00000000, 1, "1810",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+   { 0xF00A9B3C, 0x00000000, 1, "1820",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+   { 0xF0009A30, 0x00000000, 1, "1830",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+   { 0xF001DA30, 0x00000044, 1, "1833",         512,  32, 11, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX },\r
+   { 0xF001DA30, 0x00000000, 1, "1837",        1024,  32, 15, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX },\r
+   { 0xF0009830, 0x00000000, 1, "1850",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+   { 0xF001D830, 0x00000044, 1, "1853",         512,  32, 11, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // TODO - distinguish these parts (word 1)\r
+   { 0xF001D830, 0x00000000, 1, "1857",        1024,  32, 15, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // TODO - distinguish these parts (word 1)\r
+\r
+   { 0x0004FF11, 0x00000000, 0, "2103",          32,   8,  8, 4096, SectorTable_2103, CHIP_VARIANT_LPC2XXX },\r
+   { 0xFFF0FF12, 0x00000000, 0, "2104",         128,  16, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
+   { 0xFFF0FF22, 0x00000000, 0, "2105",         128,  32, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
+   { 0xFFF0FF32, 0x00000000, 0, "2106",         128,  64, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0201FF01, 0x00000000, 0, "2109",          64,   8,  8, 4096, SectorTable_2109, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0101FF12, 0x00000000, 0, "2114",         128,  16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0201FF12, 0x00000000, 0, "2119",         128,  16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0101FF13, 0x00000000, 0, "2124",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0201FF13, 0x00000000, 0, "2129",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0002FF01, 0x00000000, 0, "2131",          32,   8,  8, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0002FF11, 0x00000000, 0, "2132",          64,  16,  9, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0002FF12, 0x00000000, 0, "2134",         128,  16, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0002FF23, 0x00000000, 0, "2136",         256,  32, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0002FF25, 0x00000000, 0, "2138",         512,  32, 27, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0402FF01, 0x00000000, 0, "2141",          32,   8,  8, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0402FF11, 0x00000000, 0, "2142",          64,  16,  9, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0402FF12, 0x00000000, 0, "2144",         128,  16, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0402FF23, 0x00000000, 0, "2146",         256,  40, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0402FF25, 0x00000000, 0, "2148",         512,  40, 27, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0301FF13, 0x00000000, 0, "2194",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0301FF12, 0x00000000, 0, "2210",           0,  16,  0, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX }, /* table is a "don't care" */\r
+   { 0x0401FF12, 0x00000000, 0, "2212",         128,  16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0601FF13, 0x00000000, 0, "2214",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+   /*                           "2290"; same id as the LPC2210 */\r
+   { 0x0401FF13, 0x00000000, 0, "2292",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0501FF13, 0x00000000, 0, "2294",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1600F701, 0x00000000, 0, "2361",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 4.1 -- 5 Sep 2012 */\r
+   { 0x1600FF22, 0x00000000, 0, "2362",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 4.1 -- 5 Sep 2012 */\r
+   { 0x0603FB02, 0x00000000, 0, "2364",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+   { 0x1600F902, 0x00000000, 0, "2364",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1600E823, 0x00000000, 0, "2365",         256,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0603FB23, 0x00000000, 0, "2366",         256,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+   { 0x1600F923, 0x00000000, 0, "2366",         256,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1600E825, 0x00000000, 0, "2367",         512,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0603FB25, 0x00000000, 0, "2368",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+   { 0x1600F925, 0x00000000, 0, "2368",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1700E825, 0x00000000, 0, "2377",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x0703FF25, 0x00000000, 0, "2378",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+   { 0x1600FD25, 0x00000000, 0, "2378",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 29 October 2007 */\r
+   { 0x1700FD25, 0x00000000, 0, "2378",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1700FF35, 0x00000000, 0, "2387",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 03 -- 25 August 2008 */\r
+   { 0x1800F935, 0x00000000, 0, "2387",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1800FF35, 0x00000000, 0, "2388",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1500FF35, 0x00000000, 0, "2458",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1600FF30, 0x00000000, 0, "2460",           0,  98,  0, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1600FF35, 0x00000000, 0, "2468",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1701FF30, 0x00000000, 0, "2470",           0,  98,  0, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+   { 0x1701FF35, 0x00000000, 0, "2478",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+\r
+   { 0xA00A8B3F, 0x00000000, 1, "4310",           0, 168,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+   { 0xA0008B3C, 0x00000000, 1, "4320",           0, 200,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+   { 0xA0000A30, 0x00000000, 1, "4330",           0, 264,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+   { 0xA001CA30, 0x00000044, 1, "4333",         512, 512, 11, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* info not yet available */\r
+   { 0xA001CA30, 0x00000000, 1, "4337",        1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* info not yet available */\r
+   { 0xA0000830, 0x00000000, 1, "4350",           0, 264,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+   { 0xA001C830, 0x00000044, 1, "4353",         512, 512, 11, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+   { 0xA001C830, 0x00000000, 1, "4357",        1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+   { 0xA001C830, 0x0EF60000, 1, "4357",        1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }  /* info not yet available */\r
+};\r
+\r
+/***************************** NXP Download *********************************/\r
+/**  Download the file from the internal memory image to the NXP microcontroller.\r
+*   This function is visible from outside if COMPILE_FOR_LPC21\r
+*/\r
+\r
+/***************************** FormatCommand ********************************/\r
+/**  2013-06-28 Torsten Lang, Uwe Schneider GmbH\r
+According to the various NXP user manuals the ISP bootloader commands should\r
+be terminated with <CR><LF>, the echo and/or answer should have the same line\r
+termination. So far for the theory...\r
+In fact, the bootloader also accepts <LF> as line termination, but it may or\r
+may not echo the linebreak character. Some bootloaders convert the character\r
+into <CR><LF>, some leave the <LF> and append another one (<LF><LF> in the\r
+answer). Furthermore, during uuencoded data transfer the bootloader may or\r
+may not append an additional <LF> character at the end of the answer\r
+(leading to a <CR><LF><LF> sequence).\r
+A reliable way to handle these deviations from the UM is to strictly send the\r
+commands according to the description in the UM and to re-format commands\r
+and answers after a transfer.\r
+FormatCommand works in a way that it drops any leading linefeeds which only\r
+can be surplus <LF> characters from a previous answer. It then converts any\r
+sequence of <CR> and <LF> into a single <LF> character.\r
+FormatCommand can work in place, meaning that In==Out is allowed!\r
+\param [in]  In  Pointer to input buffer.\r
+\param [out] Out Pointer to output buffer.\r
+*/\r
+\r
+static void FormatCommand(const char *In, char *Out)\r
+{\r
+  size_t i, j;\r
+  for (i = 0, j = 0; In[j] != '\0'; i++, j++)\r
+  {\r
+    if ((In[j] == '\r') || (In[j] == '\n'))\r
+    {\r
+      if (i > 0) // Ignore leading line breaks (they must be leftovers from a previous answer)\r
+      {\r
+        Out[i] = '\n';\r
+      }\r
+      else\r
+      {\r
+        i--;\r
+      }\r
+      while ((In[j+1] == '\r') || (In[j+1] == '\n'))\r
+      {\r
+        j++;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      Out[i] = In[j];\r
+    }\r
+  }\r
+  Out[i] = '\0';\r
+}\r
+\r
+static int SendAndVerify(ISP_ENVIRONMENT *IspEnvironment, const char *Command,\r
+                                 char *AnswerBuffer, int AnswerLength)\r
+{\r
+    unsigned long realsize;\r
+    int cmdlen;\r
+    char *FormattedCommand;\r
+\r
+    SendComPort(IspEnvironment, Command);\r
+    ReceiveComPort(IspEnvironment, AnswerBuffer, AnswerLength - 1, &realsize, 2, 5000);\r
+\r
+    cmdlen = strlen(Command);\r
+    FormattedCommand = (char *)alloca(cmdlen+1);\r
+    FormatCommand(Command, FormattedCommand);\r
+    FormatCommand(AnswerBuffer, AnswerBuffer);\r
+    cmdlen = strlen(FormattedCommand);\r
+    return (strncmp(AnswerBuffer, FormattedCommand, cmdlen) == 0\r
+        && strcmp(AnswerBuffer + cmdlen, "0\n") == 0);\r
+}\r
+\r
+\r
+\r
+/***************************** NxpOutputErrorMessage ***********************/\r
+/**  Given an error number find and print the appropriate error message.\r
+\param [in] ErrorNumber The number of the error.\r
+*/\r
+#if defined COMPILE_FOR_LPC21\r
+\r
+#define NxpOutputErrorMessage(in)        // Cleanly remove this feature from the embedded version !!\r
+\r
+#else\r
+\r
+static void NxpOutputErrorMessage(unsigned char ErrorNumber)\r
+{\r
+    switch (ErrorNumber)\r
+    {\r
+    case   0:\r
+        DebugPrintf(1, "CMD_SUCCESS\n");\r
+        break;\r
+\r
+    case   1:\r
+        DebugPrintf(1, "INVALID_COMMAND\n");\r
+        break;\r
+\r
+    case   2:\r
+        DebugPrintf(1, "SRC_ADDR_ERROR: Source address is not on word boundary.\n");\r
+        break;\r
+    case   3:\r
+        DebugPrintf(1, "DST_ADDR_ERROR: Destination address is not on a correct boundary.\n");\r
+        break;\r
+\r
+    case   4:\r
+        DebugPrintf(1, "SRC_ADDR_NOT_MAPPED: Source address is not mapped in the memory map.\n"\r
+                       "                     Count value is taken into consideration where applicable.\n");\r
+        break;\r
+\r
+    case   5:\r
+        DebugPrintf(1, "DST_ADDR_NOT_MAPPED: Destination address is not mapped in the memory map.\n"\r
+                       "                     Count value is taken into consideration where applicable.\n");\r
+        break;\r
+\r
+    case   6:\r
+        DebugPrintf(1, "COUNT_ERROR: Byte count is not multiple of 4 or is not a permitted value.\n");\r
+        break;\r
+\r
+    case   7:\r
+        DebugPrintf(1, "INVALID_SECTOR: Sector number is invalid or end sector number is\n"\r
+                       "                greater than start sector number.\n");\r
+        break;\r
+\r
+    case   8:\r
+        DebugPrintf(1, "SECTOR_NOT_BLANK\n");\r
+        break;\r
+\r
+    case   9:\r
+        DebugPrintf(1, "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION:\n"\r
+                       "Command to prepare sector for write operation was not executed.\n");\r
+        break;\r
+\r
+    case  10:\r
+        DebugPrintf(1, "COMPARE_ERROR: Source and destination data not equal.\n");\r
+        break;\r
+\r
+    case  11:\r
+        DebugPrintf(1, "BUSY: Flash programming hardware interface is busy.\n");\r
+        break;\r
+\r
+    case  12:\r
+        DebugPrintf(1, "PARAM_ERROR: Insufficient number of parameters or invalid parameter.\n");\r
+        break;\r
+\r
+    case  13:\r
+        DebugPrintf(1, "ADDR_ERROR: Address is not on word boundary.\n");\r
+        break;\r
+\r
+    case  14:\r
+        DebugPrintf(1, "ADDR_NOT_MAPPED: Address is not mapped in the memory map.\n"\r
+                       "                 Count value is taken in to consideration where applicable.\n");\r
+        break;\r
+\r
+    case  15:\r
+        DebugPrintf(1, "CMD_LOCKED\n");\r
+        break;\r
+\r
+    case  16:\r
+        DebugPrintf(1, "INVALID_CODE: Unlock code is invalid.\n");\r
+        break;\r
+\r
+    case  17:\r
+        DebugPrintf(1, "INVALID_BAUD_RATE: Invalid baud rate setting.\n");\r
+        break;\r
+\r
+    case  18:\r
+        DebugPrintf(1, "INVALID_STOP_BIT: Invalid stop bit setting.\n");\r
+        break;\r
+\r
+    case  19:\r
+        DebugPrintf( 1, "CODE READ PROTECTION ENABLED\n");\r
+        break;\r
+\r
+    case 255:\r
+        break;\r
+\r
+    default:\r
+        DebugPrintf(1, "unknown error %u\n", ErrorNumber);\r
+        break;\r
+    }\r
+\r
+    //DebugPrintf(1, "error (%u), see  NxpOutputErrorMessage() in lpc21isp.c for help \n\r", ErrorNumber);\r
+}\r
+#endif // !defined COMPILE_FOR_LPC21\r
+\r
+/***************************** GetAndReportErrorNumber ***************************/\r
+/**  Find error number in string.  This will normally be the string\r
+returned from the microcontroller.\r
+\param [in] Answer the buffer to search for the error number.\r
+\return the error number found, if no linefeed found before the end of the\r
+string an error value of 255 is returned. If a non-numeric value is found\r
+then it is printed to stdout and an error value of 255 is returned.\r
+*/\r
+static unsigned char GetAndReportErrorNumber(const char *Answer)\r
+{\r
+    unsigned char Result = 0xFF;                            // Error !!!\r
+    unsigned int i = 0;\r
+\r
+    while (1)\r
+    {\r
+        if (Answer[i] == 0x00)\r
+        {\r
+            break;\r
+        }\r
+\r
+        if (Answer[i] == 0x0a)\r
+        {\r
+            i++;\r
+\r
+            if (Answer[i] < '0' || Answer[i] > '9')\r
+            {\r
+                DebugPrintf(1, "ErrorString: %s", &Answer[i]);\r
+                break;\r
+            }\r
+\r
+            Result = (unsigned char) (atoi(&Answer[i]));\r
+            break;\r
+        }\r
+\r
+        i++;\r
+    }\r
+\r
+    NxpOutputErrorMessage(Result);\r
+\r
+    return Result;\r
+}\r
+\r
+\r
+int NxpDownload(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+    unsigned long realsize;\r
+    char Answer[128];\r
+    char ExpectedAnswer[128];\r
+    char temp[128];\r
+    /*const*/ char *strippedAnswer, *endPtr;\r
+    int  strippedsize;\r
+    int nQuestionMarks;\r
+    int found;\r
+    unsigned long Sector;\r
+    unsigned long SectorLength;\r
+    unsigned long SectorStart, SectorOffset, SectorChunk;\r
+    char tmpString[128];\r
+    char uuencode_table[64];\r
+    int Line;\r
+    unsigned long tmpStringPos;\r
+    unsigned long BlockOffset;\r
+    unsigned long Block;\r
+    unsigned long Pos;\r
+    unsigned long Id[2];\r
+    unsigned long CopyLength;\r
+    int c,k=0,i;\r
+    unsigned long ivt_CRC;          // CRC over interrupt vector table\r
+    unsigned long block_CRC;\r
+    time_t tStartUpload=0, tDoneUpload=0;\r
+    char tmp_string[64];\r
+    char * cmdstr;\r
+\r
+#if !defined COMPILE_FOR_LPC21\r
+\r
+#if defined __BORLANDC__\r
+#define local_static static\r
+#else\r
+#define local_static\r
+#endif\r
+\r
+//    char * cmdstr;\r
+    int repeat = 0;\r
+    // Puffer for data to resend after "RESEND\r\n" Target responce\r
+    local_static char sendbuf0[128];\r
+    local_static char sendbuf1[128];\r
+    local_static char sendbuf2[128];\r
+    local_static char sendbuf3[128];\r
+    local_static char sendbuf4[128];\r
+    local_static char sendbuf5[128];\r
+    local_static char sendbuf6[128];\r
+    local_static char sendbuf7[128];\r
+    local_static char sendbuf8[128];\r
+    local_static char sendbuf9[128];\r
+    local_static char sendbuf10[128];\r
+    local_static char sendbuf11[128];\r
+    local_static char sendbuf12[128];\r
+    local_static char sendbuf13[128];\r
+    local_static char sendbuf14[128];\r
+    local_static char sendbuf15[128];\r
+    local_static char sendbuf16[128];\r
+    local_static char sendbuf17[128];\r
+    local_static char sendbuf18[128];\r
+    local_static char sendbuf19[128];\r
+\r
+    char * sendbuf[20] = {    sendbuf0,  sendbuf1,  sendbuf2,  sendbuf3,  sendbuf4,\r
+                              sendbuf5,  sendbuf6,  sendbuf7,  sendbuf8,  sendbuf9,\r
+                              sendbuf10, sendbuf11, sendbuf12, sendbuf13, sendbuf14,\r
+                              sendbuf15, sendbuf16, sendbuf17, sendbuf18, sendbuf19};\r
+#endif\r
+\r
+    DebugPrintf(2, "Synchronizing (ESC to abort)");\r
+\r
+    PrepareKeyboardTtySettings();\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+    if (IspEnvironment->NoSync)\r
+    {\r
+        found = 1;\r
+    }\r
+    else\r
+#endif\r
+    {\r
+        for (nQuestionMarks = found = 0; !found && nQuestionMarks < IspEnvironment->nQuestionMarks; nQuestionMarks++)\r
+        {\r
+#if defined INTEGRATED_IN_WIN_APP\r
+            // allow calling application to abort when syncing takes too long\r
+\r
+            if (!AppSyncing(nQuestionMarks))\r
+            {\r
+                return (USER_ABORT_SYNC);\r
+            }\r
+#else\r
+#ifndef Exclude_kbhit\r
+            if (kbhit())\r
+            {\r
+                if (getch() == 0x1b)\r
+                {\r
+                    ResetKeyboardTtySettings();\r
+                    DebugPrintf(2, "\nUser aborted during synchronisation\n");\r
+                    return (USER_ABORT_SYNC);\r
+                }\r
+            }\r
+#endif\r
+#endif\r
+\r
+            DebugPrintf(2, ".");\r
+            SendComPort(IspEnvironment, "?");\r
+\r
+            memset(Answer,0,sizeof(Answer));\r
+            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,100);\r
+\r
+            strippedAnswer = Answer;\r
+            strippedsize = realsize;\r
+            while ((strippedsize > 0) && ((*strippedAnswer == '?') || (*strippedAnswer == 0)))\r
+            {\r
+                strippedAnswer++;\r
+                strippedsize--;\r
+            }\r
+\r
+            sprintf(tmp_string, "StrippedAnswer(Length=%d): ", strippedsize);\r
+            DumpString(3, strippedAnswer, strippedsize, tmp_string);\r
+\r
+            tStartUpload = time(NULL);\r
+\r
+            FormatCommand(strippedAnswer, strippedAnswer);\r
+            if (strcmp(strippedAnswer, "Synchronized\n") == 0)\r
+            {\r
+                found = 1;\r
+            }\r
+#if !defined COMPILE_FOR_LPC21\r
+            else\r
+            {\r
+                ResetTarget(IspEnvironment, PROGRAM_MODE);\r
+            }\r
+#endif\r
+        }\r
+    }\r
+\r
+    ResetKeyboardTtySettings();\r
+\r
+    if (!found)\r
+    {\r
+        DebugPrintf(1, " no answer on '?'\n");\r
+        return (NO_ANSWER_QM);\r
+    }\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+    AppSyncing(-1);                         // flag syncing done\r
+#endif\r
+\r
+    DebugPrintf(2, " OK\n");\r
+\r
+    SendComPort(IspEnvironment, "Synchronized\r\n");\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer) - 1, &realsize, 2, 1000);\r
+\r
+    FormatCommand(Answer, Answer);\r
+    if (strcmp(Answer, "Synchronized\nOK\n") != 0)\r
+    {\r
+        DebugPrintf(1, "No answer on 'Synchronized'\n");\r
+        return (NO_ANSWER_SYNC);\r
+    }\r
+\r
+    DebugPrintf(3, "Synchronized 1\n");\r
+\r
+    DebugPrintf(3, "Setting oscillator\n");\r
+\r
+    sprintf(temp, "%s\r\n", IspEnvironment->StringOscillator);\r
+\r
+    SendComPort(IspEnvironment, temp);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 1000);\r
+\r
+    sprintf(temp, "%s\nOK\n", IspEnvironment->StringOscillator);\r
+\r
+    FormatCommand(Answer, Answer);\r
+    if (strcmp(Answer, temp) != 0)\r
+    {\r
+        DebugPrintf(1, "No answer on Oscillator-Command\n");\r
+        return (NO_ANSWER_OSC);\r
+    }\r
+\r
+    DebugPrintf(3, "Unlock\n");\r
+\r
+    cmdstr = "U 23130\r\n";\r
+\r
+    if (!SendAndVerify(IspEnvironment, cmdstr, Answer, sizeof Answer))\r
+    {\r
+        DebugPrintf(1, "Unlock-Command:\n");\r
+        return (UNLOCK_ERROR + GetAndReportErrorNumber(Answer));\r
+    }\r
+\r
+    DebugPrintf(2, "Read bootcode version: ");\r
+\r
+    cmdstr = "K\r\n";\r
+\r
+    SendComPort(IspEnvironment, cmdstr);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 4,5000);\r
+\r
+    FormatCommand(cmdstr, temp);\r
+    FormatCommand(Answer, Answer);\r
+    if (strncmp(Answer, temp, strlen(temp)) != 0)\r
+    {\r
+        DebugPrintf(1, "no answer on Read Boot Code Version\n");\r
+        return (NO_ANSWER_RBV);\r
+    }\r
+\r
+    if (strncmp(Answer + strlen(temp), "0\n", 2) == 0)\r
+    {\r
+        strippedAnswer = Answer + strlen(temp) + 2;\r
+        /*\r
+        int maj, min, build;\r
+        if (sscanf(strippedAnswer, "%d %d %d", &build, &min, &maj) == 2) {\r
+        maj = min;\r
+        min = build;\r
+        build = 0;\r
+        } // if\r
+        DebugPrintf(2, "%d.%d.%d\n", maj, min, build);\r
+        */\r
+        DebugPrintf(2, strippedAnswer);\r
+    }\r
+    else\r
+    {\r
+        DebugPrintf(2, "unknown\n");\r
+    }\r
+\r
+    DebugPrintf(2, "Read part ID: ");\r
+\r
+    cmdstr = "J\r\n";\r
+\r
+    SendComPort(IspEnvironment, cmdstr);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 3, 5000);\r
+\r
+    FormatCommand(cmdstr, temp);\r
+    FormatCommand(Answer, Answer);\r
+    if (strncmp(Answer, temp, strlen(temp)) != 0)\r
+    {\r
+        DebugPrintf(1, "no answer on Read Part Id\n");\r
+        return (NO_ANSWER_RPID);\r
+    }\r
+\r
+    strippedAnswer = (strncmp(Answer, "J\n0\n", 4) == 0) ? Answer + 4 : Answer;\r
+\r
+    Id[0] = strtoul(strippedAnswer, &endPtr, 10);\r
+    Id[1] = 0UL;\r
+    *endPtr = '\0'; /* delete \r\n */\r
+    for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && LPCtypes[i].id != Id[0]; i--)\r
+        /* nothing */;\r
+    IspEnvironment->DetectedDevice = i;\r
+    if (LPCtypes[IspEnvironment->DetectedDevice].EvalId2 != 0)\r
+    {\r
+        /* Read out the second configuration word and run the search again */\r
+        *endPtr = '\n';\r
+        endPtr++;\r
+        if ((endPtr[0] == '\0') || (endPtr[strlen(endPtr)-1] != '\n'))\r
+        {\r
+            /* No or incomplete word 2 */\r
+            ReceiveComPort(IspEnvironment, endPtr, sizeof(Answer)-(endPtr-Answer)-1, &realsize, 1, 100);\r
+        }\r
+\r
+        FormatCommand(endPtr, endPtr);\r
+        if ((*endPtr == '\0') || (*endPtr == '\n'))\r
+        {\r
+            DebugPrintf(1, "incomplete answer on Read Part Id (second configuration word missing)\n");\r
+            return (NO_ANSWER_RPID);\r
+        }\r
+\r
+        Id[1] = strtoul(endPtr, &endPtr, 10);\r
+        *endPtr = '\0'; /* delete \r\n */\r
+\r
+        /* now search the table again */\r
+        for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && (LPCtypes[i].id != Id[0] || LPCtypes[i].id2 != Id[1]); i--)\r
+            /* nothing */;\r
+        IspEnvironment->DetectedDevice = i;\r
+    }\r
+    if (IspEnvironment->DetectedDevice == 0) {\r
+        DebugPrintf(2, "unknown");\r
+    }\r
+    else {\r
+        DebugPrintf(2, "LPC%s, %d kiB FLASH / %d kiB SRAM",\r
+            LPCtypes[IspEnvironment->DetectedDevice].Product,\r
+            LPCtypes[IspEnvironment->DetectedDevice].FlashSize,\r
+            LPCtypes[IspEnvironment->DetectedDevice].RAMSize);\r
+    }\r
+    if (LPCtypes[IspEnvironment->DetectedDevice].EvalId2 != 0)\r
+    {\r
+        DebugPrintf(2, " (0x%08lX / 0x%08lX)\n", Id[0], Id[1]);\r
+    }\r
+    else\r
+    {\r
+        DebugPrintf(2, " (0x%08lX)\n", Id[0]);\r
+    }\r
+\r
+    if (!IspEnvironment->DetectOnly)\r
+    {\r
+        // Build up uuencode table\r
+        uuencode_table[0] = 0x60;           // 0x20 is translated to 0x60 !\r
+\r
+        for (i = 1; i < 64; i++)\r
+        {\r
+            uuencode_table[i] = (char)(0x20 + i);\r
+        }\r
+\r
+        if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+        {\r
+            // Patch 0x14, otherwise it is not running and jumps to boot mode\r
+\r
+            ivt_CRC = 0;\r
+\r
+            // Clear the vector at 0x14 so it doesn't affect the checksum:\r
+            for (i = 0; i < 4; i++)\r
+            {\r
+                IspEnvironment->BinaryContent[i + 0x14] = 0;\r
+            }\r
+\r
+            // Calculate a native checksum of the little endian vector table:\r
+            for (i = 0; i < (4 * 8);) {\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++];\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;\r
+            }\r
+\r
+            /* Negate the result and place in the vector at 0x14 as little endian\r
+            * again. The resulting vector table should checksum to 0. */\r
+            ivt_CRC = (unsigned long) (0 - ivt_CRC);\r
+            for (i = 0; i < 4; i++)\r
+            {\r
+                IspEnvironment->BinaryContent[i + 0x14] = (unsigned char)(ivt_CRC >> (8 * i));\r
+            }\r
+\r
+            DebugPrintf(3, "Position 0x14 patched: ivt_CRC = 0x%08lX\n", ivt_CRC);\r
+        }\r
+        else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+        {\r
+            // Patch 0x1C, otherwise it is not running and jumps to boot mode\r
+\r
+            ivt_CRC = 0;\r
+\r
+            // Clear the vector at 0x1C so it doesn't affect the checksum:\r
+            for (i = 0; i < 4; i++)\r
+            {\r
+                IspEnvironment->BinaryContent[i + 0x1C] = 0;\r
+            }\r
+\r
+            // Calculate a native checksum of the little endian vector table:\r
+            for (i = 0; i < (4 * 8);) {\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++];\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;\r
+                ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;\r
+            }\r
+\r
+            /* Negate the result and place in the vector at 0x1C as little endian\r
+            * again. The resulting vector table should checksum to 0. */\r
+            ivt_CRC = (unsigned long) (0 - ivt_CRC);\r
+            for (i = 0; i < 4; i++)\r
+            {\r
+                IspEnvironment->BinaryContent[i + 0x1C] = (unsigned char)(ivt_CRC >> (8 * i));\r
+            }\r
+\r
+            DebugPrintf(3, "Position 0x1C patched: ivt_CRC = 0x%08lX\n", ivt_CRC);\r
+        }\r
+        else\r
+        {\r
+          DebugPrintf(1, "Internal error: wrong chip variant %d (detected device %d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant, IspEnvironment->DetectedDevice);\r
+          exit(1);\r
+        }\r
+    }\r
+\r
+#if 0\r
+    DebugPrintf(2, "Read Unique ID:\n");\r
+\r
+    cmdstr = "N\r\n";\r
+\r
+    SendComPort(IspEnvironment, cmdstr);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 5,5000);\r
+\r
+    FormatCommand(cmdstr, temp);\r
+    FormatCommand(Answer, Answer);\r
+    if (strncmp(Answer, temp, strlen(temp)) != 0)\r
+    {\r
+        DebugPrintf(1, "no answer on Read Unique ID\n");\r
+        return (NO_ANSWER_RBV);\r
+    }\r
+\r
+    if (strncmp(Answer + strlen(cmdstr), "0\n", 2) == 0)\r
+    {\r
+        strippedAnswer = Answer + strlen(temp) + 2;\r
+        DebugPrintf(2, strippedAnswer);\r
+    }\r
+    else\r
+    {\r
+        DebugPrintf(2, "unknown\n");\r
+    }\r
+#endif // 0\r
+\r
+    /* In case of a download to RAM, use full RAM for downloading\r
+    * set the flash parameters to full RAM also.\r
+    * This makes sure that all code is downloaded as one big sector\r
+    */\r
+\r
+    if ( (IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment))\r
+       &&(IspEnvironment->BinaryOffset + IspEnvironment->BinaryLength <= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+    {\r
+        LPCtypes[IspEnvironment->DetectedDevice].FlashSectors = 1;\r
+        LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize  = LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024 - (ReturnValueLpcRamBase(IspEnvironment) - ReturnValueLpcRamStart(IspEnvironment));\r
+        LPCtypes[IspEnvironment->DetectedDevice].SectorTable  = SectorTable_RAM;\r
+        SectorTable_RAM[0] = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
+    }\r
+    if (IspEnvironment->DetectOnly)\r
+        return (0);\r
+\r
+    if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+    {\r
+      // XON/XOFF must be switched off for LPC8XX\r
+      // otherwise problem during binary transmission of data to LPC8XX\r
+      DebugPrintf(3, "Switch off XON/XOFF !!!\n");\r
+      ControlXonXoffSerialPort(IspEnvironment, 0);\r
+    }\r
+\r
+    // Start with sector 1 and go upward... Sector 0 containing the interrupt vectors\r
+    // will be loaded last, since it contains a checksum and device will re-enter\r
+    // bootloader mode as long as this checksum is invalid.\r
+    DebugPrintf(2, "Will start programming at Sector 1 if possible, and conclude with Sector 0 to ensure that checksum is written last.\n");\r
+    if (LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0] >= IspEnvironment->BinaryLength)\r
+    {\r
+        Sector = 0;\r
+        SectorStart = 0;\r
+    }\r
+    else\r
+    {\r
+        SectorStart = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0];\r
+        Sector = 1;\r
+    }\r
+\r
+    if (IspEnvironment->WipeDevice == 1)\r
+    {\r
+        DebugPrintf(2, "Wiping Device. ");\r
+\r
+        if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+            LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+        {\r
+            // TODO: Quick and dirty hack to address bank 0\r
+            sprintf(tmpString, "P %d %d 0\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+        }\r
+        else\r
+        {\r
+            sprintf(tmpString, "P %d %d\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+        }\r
+\r
+        if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+        {\r
+            DebugPrintf(1, "Wrong answer on Prepare-Command\n");\r
+            return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
+        }\r
+\r
+        if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+            LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+        {\r
+            // TODO: Quick and dirty hack to address bank 0\r
+            sprintf(tmpString, "E %d %d 0\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+        }\r
+        else\r
+        {\r
+            sprintf(tmpString, "E %d %d\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+        }\r
+        if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+        {\r
+            DebugPrintf(1, "Wrong answer on Erase-Command\n");\r
+            return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
+        }\r
+        DebugPrintf(2, "OK \n");\r
+\r
+        if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+            LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+        {\r
+          DebugPrintf(2, "ATTENTION: Only bank A was wiped!!!\n");\r
+        }\r
+    }\r
+    else{\r
+        //no wiping requested: erasing sector 0 first\r
+        DebugPrintf(2, "Erasing sector 0 first, to invalidate checksum. ");\r
+\r
+        if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+            LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+        {\r
+            // TODO: Quick and dirty hack to address bank 0\r
+            sprintf(tmpString, "P %d %d 0\r\n", 0, 0);\r
+        }\r
+        else\r
+        {\r
+            sprintf(tmpString, "P %d %d\r\n", 0, 0);\r
+        }\r
+\r
+        if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+        {\r
+            DebugPrintf(1, "Wrong answer on Prepare-Command\n");\r
+            return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
+        }\r
+\r
+        if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+            LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+        {\r
+            // TODO: Quick and dirty hack to address bank 0\r
+            sprintf(tmpString, "E %d %d 0\r\n", 0, 0);\r
+        }\r
+        else\r
+        {\r
+            sprintf(tmpString, "E %d %d\r\n", 0, 0);\r
+        }\r
+\r
+        if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+        {\r
+            DebugPrintf(1, "Wrong answer on Erase-Command\n");\r
+            return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
+        }\r
+        DebugPrintf(2, "OK \n");\r
+    }\r
+    while (1)\r
+    {\r
+        if (Sector >= LPCtypes[IspEnvironment->DetectedDevice].FlashSectors)\r
+        {\r
+            DebugPrintf(1, "Program too large; running out of Flash sectors.\n");\r
+            return (PROGRAM_TOO_LARGE);\r
+        }\r
+\r
+        DebugPrintf(2, "Sector %ld: ", Sector);\r
+        fflush(stdout);\r
+\r
+        if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))  // Skip Erase when running from RAM\r
+           ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+        {\r
+            if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+            {\r
+                // TODO: Quick and dirty hack to address bank 0\r
+                sprintf(tmpString, "P %ld %ld 0\r\n", Sector, Sector);\r
+            }\r
+            else\r
+            {\r
+                sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
+            }\r
+\r
+            if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+            {\r
+                DebugPrintf(1, "Wrong answer on Prepare-Command (1) (Sector %ld)\n", Sector);\r
+                return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
+            }\r
+\r
+            DebugPrintf(2, ".");\r
+            fflush(stdout);\r
+            if (IspEnvironment->WipeDevice == 0 && (Sector!=0)) //Sector 0 already erased\r
+            {\r
+                if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+                    LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+                {\r
+                    // TODO: Quick and dirty hack to address bank 0\r
+                    sprintf(tmpString, "E %ld %ld 0\r\n", Sector, Sector);\r
+                }\r
+                else\r
+                {\r
+                    sprintf(tmpString, "E %ld %ld\r\n", Sector, Sector);\r
+                }\r
+\r
+                if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+                {\r
+                    DebugPrintf(1, "Wrong answer on Erase-Command (Sector %ld)\n", Sector);\r
+                    return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
+                }\r
+\r
+                DebugPrintf(2, ".");\r
+                fflush(stdout);\r
+            }\r
+        }\r
+\r
+        SectorLength = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];\r
+        if (SectorLength > IspEnvironment->BinaryLength - SectorStart)\r
+        {\r
+            SectorLength = IspEnvironment->BinaryLength - SectorStart;\r
+        }\r
+\r
+        for (SectorOffset = 0; SectorOffset < SectorLength; SectorOffset += SectorChunk)\r
+        {\r
+            // Check if we are to write only 0xFFs - it would be just a waste of time..\r
+            if (SectorOffset == 0) {\r
+                for (SectorOffset = 0; SectorOffset < SectorLength; ++SectorOffset)\r
+                {\r
+                    if (IspEnvironment->BinaryContent[SectorStart + SectorOffset] != 0xFF)\r
+                        break;\r
+                }\r
+                if (SectorOffset == SectorLength) // all data contents were 0xFFs\r
+                {\r
+                    DebugPrintf(2, "Whole sector contents is 0xFFs, skipping programming.");\r
+                    fflush(stdout);\r
+                    break;\r
+                }\r
+                SectorOffset = 0; // re-set otherwise\r
+            }\r
+\r
+            if (SectorOffset > 0)\r
+            {\r
+                // Add a visible marker between segments in a sector\r
+                DebugPrintf(2, "|");  /* means: partial segment copied */\r
+                fflush(stdout);\r
+            }\r
+\r
+            // If the Flash ROM sector size is bigger than the number of bytes\r
+            // we can copy from RAM to Flash, we must "chop up" the sector and\r
+            // copy these individually.\r
+            // This is especially needed in the case where a Flash sector is\r
+            // bigger than the amount of SRAM.\r
+            SectorChunk = SectorLength - SectorOffset;\r
+            if (SectorChunk > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)\r
+            {\r
+                SectorChunk = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
+            }\r
+\r
+            // Write multiple of 45 * 4 Byte blocks to RAM, but copy maximum of on sector to Flash\r
+            // In worst case we transfer up to 180 byte too much to RAM\r
+            // but then we can always use full 45 byte blocks and length is multiple of 4\r
+            CopyLength = SectorChunk;\r
+\r
+            if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+            {\r
+                if ((CopyLength % (45 * 4)) != 0)\r
+                {\r
+                    CopyLength += ((45 * 4) - (CopyLength % (45 * 4)));\r
+                }\r
+            }\r
+\r
+            sprintf(tmpString, "W %ld %ld\r\n", ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
+\r
+            if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+            {\r
+                DebugPrintf(1, "Wrong answer on Write-Command\n");\r
+                return (WRONG_ANSWER_WRIT + GetAndReportErrorNumber(Answer));\r
+            }\r
+\r
+            DebugPrintf(2, ".");\r
+            fflush(stdout);\r
+\r
+            if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+               LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+            {\r
+                block_CRC = 0;\r
+                Line = 0;\r
+\r
+                // Transfer blocks of 45 * 4 bytes to RAM\r
+                for (Pos = SectorStart + SectorOffset; (Pos < SectorStart + SectorOffset + CopyLength) && (Pos < IspEnvironment->BinaryLength); Pos += (45 * 4))\r
+                {\r
+                    for (Block = 0; Block < 4; Block++)  // Each block 45 bytes\r
+                    {\r
+                        DebugPrintf(2, ".");\r
+                        fflush(stdout);\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+                        // inform the calling application about having written another chuck of data\r
+                        AppWritten(45);\r
+#endif\r
+\r
+                        // Uuencode one 45 byte block\r
+                        tmpStringPos = 0;\r
+\r
+#if !defined COMPILE_FOR_LPC21\r
+                        sendbuf[Line][tmpStringPos++] = (char)(' ' + 45);    // Encode Length of block\r
+#else\r
+                        tmpString[tmpStringPos++] = (char)(' ' + 45);        // Encode Length of block\r
+#endif\r
+\r
+                        for (BlockOffset = 0; BlockOffset < 45; BlockOffset++)\r
+                        {\r
+                            if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))\r
+                               ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+                            { // Flash: use full memory\r
+                                c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset];\r
+                            }\r
+                            else\r
+                            { // RAM: Skip first 0x200 bytes, these are used by the download program in LPC21xx\r
+                                c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset + 0x200];\r
+                            }\r
+\r
+                            block_CRC += c;\r
+\r
+                            k = (k << 8) + (c & 255);\r
+\r
+                            if ((BlockOffset % 3) == 2)   // Collecting always 3 Bytes, then do processing in 4 Bytes\r
+                            {\r
+#if !defined COMPILE_FOR_LPC21\r
+                                sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 18) & 63];\r
+                                sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 12) & 63];\r
+                                sendbuf[Line][tmpStringPos++] = uuencode_table[(k >>  6) & 63];\r
+                                sendbuf[Line][tmpStringPos++] = uuencode_table[ k        & 63];\r
+#else\r
+                                tmpString[tmpStringPos++] = uuencode_table[(k >> 18) & 63];\r
+                                tmpString[tmpStringPos++] = uuencode_table[(k >> 12) & 63];\r
+                                tmpString[tmpStringPos++] = uuencode_table[(k >>  6) & 63];\r
+                                tmpString[tmpStringPos++] = uuencode_table[ k        & 63];\r
+#endif\r
+                            }\r
+                        }\r
+\r
+\r
+#if !defined COMPILE_FOR_LPC21\r
+                        sendbuf[Line][tmpStringPos++] = '\r';\r
+                        sendbuf[Line][tmpStringPos++] = '\n';\r
+                        sendbuf[Line][tmpStringPos++] = 0;\r
+\r
+                        SendComPort(IspEnvironment, sendbuf[Line]);\r
+                        // receive only for debug proposes\r
+                        ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
+                        FormatCommand(sendbuf[Line], tmpString);\r
+                        FormatCommand(Answer, Answer);\r
+                        if (strncmp(Answer, tmpString, strlen(tmpString)) != 0)\r
+                        {\r
+                            DebugPrintf(1, "Error on writing data (1)\n");\r
+                            return (ERROR_WRITE_DATA);\r
+                        }\r
+#else\r
+                        tmpString[tmpStringPos++] = '\r';\r
+                        tmpString[tmpStringPos++] = '\n';\r
+                        tmpString[tmpStringPos++] = 0;\r
+\r
+                        SendComPort(IspEnvironment, tmpString);\r
+                        ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
+                        FormatCommand(tmpString, tmpString);\r
+                        FormatCommand(Answer, Answer);\r
+                        if (strncmp(Answer, tmpString, tmpStringPos) != 0)\r
+                        {\r
+                            DebugPrintf(1, "Error on writing data (1)\n");\r
+                            return (ERROR_WRITE_DATA);\r
+                        }\r
+#endif\r
+\r
+                        Line++;\r
+\r
+                        DebugPrintf(3, "Line = %d\n", Line);\r
+\r
+                        if (Line == 20)\r
+                        {\r
+#if !defined COMPILE_FOR_LPC21\r
+                            for (repeat = 0; repeat < 3; repeat++)\r
+                            {\r
+\r
+                                // DebugPrintf(1, "block_CRC = %ld\n", block_CRC);\r
+\r
+                                sprintf(tmpString, "%ld\r\n", block_CRC);\r
+\r
+                                SendComPort(IspEnvironment, tmpString);\r
+\r
+                                ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);\r
+\r
+                                sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+\r
+                                FormatCommand(tmpString, tmpString);\r
+                                FormatCommand(Answer, Answer);\r
+                                if (strcmp(Answer, tmpString) != 0)\r
+                                {\r
+                                    for (i = 0; i < Line; i++)\r
+                                    {\r
+                                        SendComPort(IspEnvironment, sendbuf[i]);\r
+                                        ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
+                                    }\r
+                                }\r
+                                else\r
+                                    break;\r
+                            }\r
+\r
+                            if (repeat >= 3)\r
+                            {\r
+                                DebugPrintf(1, "Error on writing block_CRC (1)\n");\r
+                                return (ERROR_WRITE_CRC);\r
+                            }\r
+#else\r
+                            // DebugPrintf(1, "block_CRC = %ld\n", block_CRC);\r
+                            sprintf(tmpString, "%ld\r\n", block_CRC);\r
+                            SendComPort(IspEnvironment, tmpString);\r
+\r
+                            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+                            sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+                            FormatCommand(tmpString, tmpString);\r
+                            FormatCommand(Answer, Answer);\r
+                            if (strcmp(Answer, tmpString) != 0)\r
+                            {\r
+                                DebugPrintf(1, "Error on writing block_CRC (2)\n");\r
+                                return (ERROR_WRITE_CRC);\r
+                            }\r
+#endif\r
+                            Line = 0;\r
+                            block_CRC = 0;\r
+                        }\r
+                    }\r
+                }\r
+\r
+                if (Line != 0)\r
+                {\r
+#if !defined COMPILE_FOR_LPC21\r
+                    for (repeat = 0; repeat < 3; repeat++)\r
+                    {\r
+                        sprintf(tmpString, "%ld\r\n", block_CRC);\r
+\r
+                        SendComPort(IspEnvironment, tmpString);\r
+\r
+                        ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+                        sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+\r
+                        FormatCommand(tmpString, tmpString);\r
+                        FormatCommand(Answer, Answer);\r
+                        if (strcmp(Answer, tmpString) != 0)\r
+                        {\r
+                            for (i = 0; i < Line; i++)\r
+                            {\r
+                                SendComPort(IspEnvironment, sendbuf[i]);\r
+                                ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);\r
+                            }\r
+                        }\r
+                        else\r
+                            break;\r
+                    }\r
+\r
+                    if (repeat >= 3)\r
+                    {\r
+                        DebugPrintf(1, "Error on writing block_CRC (3)\n");\r
+                        return (ERROR_WRITE_CRC2);\r
+                    }\r
+#else\r
+                    sprintf(tmpString, "%ld\r\n", block_CRC);\r
+                    SendComPort(IspEnvironment, tmpString);\r
+\r
+                    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+                    sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+                    FormatCommand(tmpString, tmpString);\r
+                    FormatCommand(Answer, Answer);\r
+                    if (strcmp(Answer, tmpString) != 0)\r
+                    {\r
+                        DebugPrintf(1, "Error on writing block_CRC (4)\n");\r
+                        return (ERROR_WRITE_CRC2);\r
+                    }\r
+#endif\r
+                }\r
+            }\r
+            else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+            {\r
+                unsigned char BigAnswer[4096];\r
+                unsigned long CopyLengthPartialOffset = 0;\r
+                unsigned long CopyLengthPartialRemainingBytes;\r
+\r
+                while(CopyLengthPartialOffset < CopyLength)\r
+                {\r
+                    CopyLengthPartialRemainingBytes = CopyLength - CopyLengthPartialOffset;\r
+                    if(CopyLengthPartialRemainingBytes > 256)\r
+                    {\r
+                      // There seems to be an error in LPC812:\r
+                      // When too much bytes are written at high speed,\r
+                      // bytes get lost\r
+                      // Workaround: Use smaller blocks\r
+                      CopyLengthPartialRemainingBytes = 256;\r
+                    }\r
+\r
+                    SendComPortBlock(IspEnvironment, &IspEnvironment->BinaryContent[SectorStart + SectorOffset + CopyLengthPartialOffset], CopyLengthPartialRemainingBytes);\r
+\r
+                    if (ReceiveComPortBlockComplete(IspEnvironment, &BigAnswer, CopyLengthPartialRemainingBytes, 10000) != 0)\r
+                    {\r
+                        return (ERROR_WRITE_DATA);\r
+                    }\r
+\r
+                    if(memcmp(&IspEnvironment->BinaryContent[SectorStart + SectorOffset + CopyLengthPartialOffset], BigAnswer, CopyLengthPartialRemainingBytes))\r
+                    {\r
+                        return (ERROR_WRITE_DATA);\r
+                    }\r
+\r
+                    CopyLengthPartialOffset += CopyLengthPartialRemainingBytes;\r
+                }\r
+            }\r
+\r
+            if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))\r
+               ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+            {\r
+                // Prepare command must be repeated before every write\r
+                if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+                    LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+                {\r
+                    // TODO: Quick and dirty hack to address bank 0\r
+                    sprintf(tmpString, "P %ld %ld 0\r\n", Sector, Sector);\r
+                }\r
+                else\r
+                {\r
+                    sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
+                }\r
+\r
+                if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+                {\r
+                    DebugPrintf(1, "Wrong answer on Prepare-Command (2) (Sector %ld)\n", Sector);\r
+                    return (WRONG_ANSWER_PREP2 + GetAndReportErrorNumber(Answer));\r
+                }\r
+\r
+                // Round CopyLength up to one of the following values: 512, 1024,\r
+                // 4096, 8192; but do not exceed the maximum copy size (usually\r
+                // 8192, but chip-dependent)\r
+                if (CopyLength < 512)\r
+                {\r
+                    CopyLength = 512;\r
+                }\r
+                else if (SectorLength < 1024)\r
+                {\r
+                    CopyLength = 1024;\r
+                }\r
+                else if (SectorLength < 4096)\r
+                {\r
+                    CopyLength = 4096;\r
+                }\r
+                else\r
+                {\r
+                    CopyLength = 8192;\r
+                }\r
+                if (CopyLength > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)\r
+                {\r
+                    CopyLength = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
+                }\r
+\r
+                sprintf(tmpString, "C %ld %ld %ld\r\n", IspEnvironment->BinaryOffset + SectorStart + SectorOffset, ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
+\r
+                if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+                {\r
+                    DebugPrintf(1, "Wrong answer on Copy-Command\n");\r
+                    return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));\r
+                }\r
+\r
+                if (IspEnvironment->Verify)\r
+                {\r
+\r
+                    //Avoid compare first 64 bytes.\r
+                    //Because first 64 bytes are re-mapped to flash boot sector,\r
+                    //and the compare result may not be correct.\r
+                    if (SectorStart + SectorOffset<64)\r
+                    {\r
+                        sprintf(tmpString, "M %d %ld %ld\r\n", 64, ReturnValueLpcRamBase(IspEnvironment) + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));\r
+                    }\r
+                    else\r
+                    {\r
+                        sprintf(tmpString, "M %ld %ld %ld\r\n", SectorStart + SectorOffset, ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
+                    }\r
+\r
+                    if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+                    {\r
+                        DebugPrintf(1, "Wrong answer on Compare-Command\n");\r
+                        return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        DebugPrintf(2, "\n");\r
+        fflush(stdout);\r
+\r
+        if ((SectorStart + SectorLength) >= IspEnvironment->BinaryLength && Sector!=0)\r
+        {\r
+            Sector = 0;\r
+            SectorStart = 0;\r
+        }\r
+        else if (Sector == 0) {\r
+            break;\r
+        }\r
+        else {\r
+            SectorStart += LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];\r
+            Sector++;\r
+        }\r
+    }\r
+\r
+    tDoneUpload = time(NULL);\r
+    if (IspEnvironment->Verify)\r
+        DebugPrintf(2, "Download Finished and Verified correct... taking %d seconds\n", tDoneUpload - tStartUpload);\r
+    else\r
+        DebugPrintf(2, "Download Finished... taking %d seconds\n", tDoneUpload - tStartUpload);\r
+\r
+    // For LPC18xx set boot bank to 0\r
+    if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+        LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+    {\r
+        if (!SendAndVerify(IspEnvironment, "S 0\r\n", Answer, sizeof Answer))\r
+        {\r
+            DebugPrintf(1, "Wrong answer on SetActiveBootFlashBank-Command\n");\r
+            return (WRONG_ANSWER_BTBNK + GetAndReportErrorNumber(Answer));\r
+        }\r
+    }\r
+\r
+    if(IspEnvironment->DoNotStart == 0)\r
+    {\r
+        DebugPrintf(2, "Now launching the brand new code\n");\r
+        fflush(stdout);\r
+\r
+        if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+        {\r
+            sprintf(tmpString, "G %ld A\r\n", IspEnvironment->StartAddress);\r
+        }\r
+        else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+        {\r
+            sprintf(tmpString, "G %ld T\r\n", IspEnvironment->StartAddress & ~1);\r
+        }\r
+        else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+        {\r
+            sprintf(tmpString, "G 0 T\r\n");\r
+        }\r
+        else\r
+        {\r
+            DebugPrintf(1, "Internal Error %s %d\n", __FILE__, __LINE__);\r
+            exit(1);\r
+        }\r
+\r
+        SendComPort(IspEnvironment, tmpString); //goto 0 : run this fresh new downloaded code code\r
+        if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))\r
+           ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+        { // Skip response on G command - show response on Terminal instead\r
+            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);\r
+            /* the reply string is frequently terminated with a -1 (EOF) because the\r
+            * connection gets broken; zero-terminate the string ourselves\r
+            */\r
+            while (realsize > 0 && ((signed char) Answer[(int)realsize - 1]) < 0)\r
+                realsize--;\r
+            Answer[(int)realsize] = '\0';\r
+            /* Better to check only the first 9 chars instead of complete receive buffer,\r
+            * because the answer can contain the output by the started programm\r
+            */\r
+            if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+            {\r
+                sprintf(ExpectedAnswer, "G %ld A\n0", IspEnvironment->StartAddress);\r
+            }\r
+            else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+                    LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+                    LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+                    LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+                    LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+            {\r
+                sprintf(ExpectedAnswer, "G %ld T\n0", IspEnvironment->StartAddress & ~1);\r
+            }\r
+            else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+            {\r
+                sprintf(ExpectedAnswer, "G 0 T\n0");\r
+            }\r
+            else\r
+            {\r
+                DebugPrintf(1, "Internal Error %s %d\n", __FILE__, __LINE__);\r
+                exit(1);\r
+            }\r
+\r
+            FormatCommand(Answer, Answer);\r
+            if (realsize == 0 || strncmp((const char *)Answer, /*cmdstr*/ExpectedAnswer, strlen(/*cmdstr*/ExpectedAnswer)) != 0)\r
+            {\r
+                DebugPrintf(2, "Failed to run the new downloaded code: ");\r
+                return (FAILED_RUN + GetAndReportErrorNumber(Answer));\r
+            }\r
+        }\r
+\r
+        fflush(stdout);\r
+    }\r
+    return (0);\r
+}\r
+#endif // LPC_SUPPORT\r
+\r
+\r
+unsigned long ReturnValueLpcRamStart(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+  if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+  {\r
+    return LPC_RAMSTART_LPC43XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+  {\r
+    return LPC_RAMSTART_LPC2XXX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+  {\r
+    return LPC_RAMSTART_LPC18XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX)\r
+  {\r
+    return LPC_RAMSTART_LPC17XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX)\r
+  {\r
+    return LPC_RAMSTART_LPC13XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+  {\r
+    return LPC_RAMSTART_LPC11XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+  {\r
+    return LPC_RAMSTART_LPC8XX;\r
+  }\r
+  DebugPrintf(1, "Error in ReturnValueLpcRamStart (%d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant);\r
+  exit(1);\r
+}\r
+\r
+\r
+unsigned long ReturnValueLpcRamBase(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+  if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+  {\r
+    return LPC_RAMBASE_LPC43XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+  {\r
+    return LPC_RAMBASE_LPC2XXX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+  {\r
+    return LPC_RAMBASE_LPC18XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX)\r
+  {\r
+    return LPC_RAMBASE_LPC17XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX)\r
+  {\r
+    return LPC_RAMBASE_LPC13XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+  {\r
+    return LPC_RAMBASE_LPC11XX;\r
+  }\r
+  else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+  {\r
+    return LPC_RAMBASE_LPC8XX;\r
+  }\r
+  DebugPrintf(1, "Error in ReturnValueLpcRamBase (%d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant);\r
+  exit(1);\r
+}\r
diff --git a/host/app/lpc21lisp/lpcprog.h b/host/app/lpc21lisp/lpcprog.h
new file mode 100644 (file)
index 0000000..3e60b3e
--- /dev/null
@@ -0,0 +1,144 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          lpcprog.h\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+/* LPC_RAMSTART, LPC_RAMBASE\r
+*\r
+* Used in NxpDownload() to decide whether to Flash code or just place in in RAM\r
+* (works for .hex files only)\r
+*\r
+* LPC_RAMSTART - the Physical start address of the SRAM\r
+* LPC_RAMBASE  - the base address where downloading starts.\r
+*                Note that any code in the .hex file that resides in 0x4000,0000 ~ 0x4000,0200\r
+*                will _not_ be written to the LPCs SRAM.\r
+*                This is due to the fact that 0x4000,0040 - 0x4000,0200 is used by the bootrom.\r
+*                Any interrupt vectors must be copied to 0x4000,0000 and remapped to 0x0000,0000\r
+*                by the startup code.\r
+*/\r
+#define LPC_RAMSTART_LPC43XX    0x10000000L\r
+#define LPC_RAMBASE_LPC43XX     0x10000200L\r
+\r
+#define LPC_RAMSTART_LPC2XXX    0x40000000L\r
+#define LPC_RAMBASE_LPC2XXX     0x40000200L\r
+\r
+#define LPC_RAMSTART_LPC18XX    0x10000000L\r
+#define LPC_RAMBASE_LPC18XX     0x10000200L\r
+\r
+#define LPC_RAMSTART_LPC17XX    0x10000000L\r
+#define LPC_RAMBASE_LPC17XX     0x10000200L\r
+\r
+#define LPC_RAMSTART_LPC13XX    0x10000000L\r
+#define LPC_RAMBASE_LPC13XX     0x10000300L\r
+\r
+#define LPC_RAMSTART_LPC11XX    0x10000000L\r
+#define LPC_RAMBASE_LPC11XX     0x10000300L\r
+\r
+#define LPC_RAMSTART_LPC8XX     0x10000000L\r
+#define LPC_RAMBASE_LPC8XX      0x10000270L\r
+\r
+/* Return values used by NxpDownload(): reserving all values from 0x1000 to 0x1FFF */\r
+\r
+#define NO_ANSWER_WDT       0x1000\r
+#define NO_ANSWER_QM        0x1001\r
+#define NO_ANSWER_SYNC      0x1002\r
+#define NO_ANSWER_OSC       0x1003\r
+#define NO_ANSWER_RBV       0x1004\r
+#define NO_ANSWER_RPID      0x1005\r
+#define ERROR_WRITE_DATA    0x1006\r
+#define ERROR_WRITE_CRC     0x1007\r
+#define ERROR_WRITE_CRC2    0x1008\r
+#define PROGRAM_TOO_LARGE   0x1009\r
+\r
+#define USER_ABORT_SYNC     0x100A   /* User aborted synchronisation process */\r
+\r
+#define UNKNOWN_LPC         0x100B   /* Unknown LPC detected */\r
+\r
+#define UNLOCK_ERROR        0x1100   /* return value is 0x1100 + NXP ISP returned value (0 to 255) */\r
+#define WRONG_ANSWER_PREP   0x1200   /* return value is 0x1200 + NXP ISP returned value (0 to 255) */\r
+#define WRONG_ANSWER_ERAS   0x1300   /* return value is 0x1300 + NXP ISP returned value (0 to 255) */\r
+#define WRONG_ANSWER_WRIT   0x1400   /* return value is 0x1400 + NXP ISP returned value (0 to 255) */\r
+#define WRONG_ANSWER_PREP2  0x1500   /* return value is 0x1500 + NXP ISP returned value (0 to 255) */\r
+#define WRONG_ANSWER_COPY   0x1600   /* return value is 0x1600 + NXP ISP returned value (0 to 255) */\r
+#define FAILED_RUN          0x1700   /* return value is 0x1700 + NXP ISP returned value (0 to 255) */\r
+#define WRONG_ANSWER_BTBNK  0x1800   /* return value is 0x1800 + NXP ISP returned value (0 to 255) */\r
+\r
+#if defined COMPILE_FOR_LPC21\r
+#ifndef WIN32\r
+#define LPC_BSL_PIN         13\r
+#define LPC_RESET_PIN       47\r
+#define LPC_RESET(in)       NAsetGPIOpin(LPC_RESET_PIN, (in))\r
+#define LPC_BSL(in)         NAsetGPIOpin(LPC_BSL_PIN,   (in))\r
+#endif // WIN32\r
+#endif // COMPILE_FOR_LPC21\r
+\r
+\r
+/* LPC_FLASHMASK\r
+*\r
+* LPC_FLASHMASK - bitmask to define the maximum size of the Filesize to download.\r
+*                 LoadFile() will check any new segment address record (03) or extended linear\r
+*                 address record (04) to see if the addressed 64 kByte data block still falls\r
+*                 in the max. flash size.\r
+*                 LoadFile() will not load any files that are larger than this size.\r
+*/\r
+#define LPC_FLASHMASK  0xFFC00000 /* 22 bits = 4 MB */\r
+\r
+typedef enum\r
+  {\r
+  CHIP_VARIANT_NONE,\r
+  CHIP_VARIANT_LPC43XX,\r
+  CHIP_VARIANT_LPC2XXX,\r
+  CHIP_VARIANT_LPC18XX,\r
+  CHIP_VARIANT_LPC17XX,\r
+  CHIP_VARIANT_LPC13XX,\r
+  CHIP_VARIANT_LPC11XX,\r
+  CHIP_VARIANT_LPC8XX\r
+  } CHIP_VARIANT;\r
+\r
+typedef struct\r
+{\r
+    const unsigned long  id;\r
+    const unsigned long  id2;\r
+    const unsigned int   EvalId2;\r
+    const char *Product;\r
+    const unsigned int   FlashSize;     /* in kiB, for informational purposes only */\r
+    const unsigned int   RAMSize;       /* in kiB, for informational purposes only */\r
+          unsigned int   FlashSectors;  /* total number of sectors */\r
+          unsigned int   MaxCopySize;   /* maximum size that can be copied to Flash in a single command */\r
+    const unsigned int  *SectorTable;   /* pointer to a sector table with constant the sector sizes */\r
+    const CHIP_VARIANT   ChipVariant;\r
+} LPC_DEVICE_TYPE;\r
+\r
+int NxpDownload(ISP_ENVIRONMENT *IspEnvironment);\r
+\r
+unsigned long ReturnValueLpcRamStart(ISP_ENVIRONMENT *IspEnvironment);\r
+\r
+unsigned long ReturnValueLpcRamBase(ISP_ENVIRONMENT *IspEnvironment);\r
+\r
diff --git a/host/app/lpc21lisp/lpcterm.c b/host/app/lpc21lisp/lpcterm.c
new file mode 100644 (file)
index 0000000..e176a6d
--- /dev/null
@@ -0,0 +1,138 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          lpcterm.c\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#if defined(_WIN32)\r
+#if !defined __BORLANDC__\r
+#include "StdAfx.h"\r
+#endif\r
+#endif // defined(_WIN32)\r
+#include "lpc21isp.h"\r
+#include "lpcterm.h"\r
+\r
+#ifdef TERMINAL_SUPPORT\r
+/***************************** Terminal *********************************/\r
+/**  Acts as a simple dumb terminal. Press 'ESC' to exit.\r
+*/\r
+BOOL CheckTerminalParameters(ISP_ENVIRONMENT *IspEnvironment, char* pstr)\r
+{\r
+    if (stricmp(pstr, "-localecho") == 0)\r
+    {\r
+        IspEnvironment->LocalEcho = 1;\r
+        DebugPrintf(3, "Local echo in terminal mode.\n");\r
+        return TRUE;\r
+    }\r
+\r
+    if (stricmp(pstr, "-term") == 0)\r
+    {\r
+        IspEnvironment->TerminalAfterUpload = 1;\r
+        DebugPrintf(3, "Invoke terminal after upload.\n");\r
+        return TRUE;\r
+    }\r
+\r
+    if (stricmp(pstr, "-termonly") == 0)\r
+    {\r
+        IspEnvironment->TerminalOnly    = 1;\r
+        IspEnvironment->ProgramChip    = 0;\r
+        DebugPrintf(3, "Only provide terminal.\n");\r
+        return TRUE;\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+void Terminal(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+    if (IspEnvironment->TerminalAfterUpload || IspEnvironment->TerminalOnly)\r
+    {\r
+        int           ch = 0;\r
+        char buffer[128];\r
+        int           fdlogfile = -1;\r
+        unsigned long realsize;\r
+\r
+        // When logging is switched on, output terminal output to lpc21isp.log\r
+        if (IspEnvironment->LogFile)\r
+        {\r
+            fdlogfile = open("lpc21isp.log", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);\r
+        }\r
+\r
+        PrepareKeyboardTtySettings();\r
+\r
+        DebugPrintf(1, "Terminal started (press Escape to abort)\n\n");\r
+        fflush(stdout);\r
+\r
+        do\r
+        {\r
+            ReceiveComPort(IspEnvironment, buffer, sizeof(buffer) - 1, &realsize, 0,200);          // Check for received characters\r
+\r
+            if (realsize)\r
+            {\r
+                write(1, buffer, realsize);\r
+                fflush(stdout);\r
+                if (IspEnvironment->LogFile)     // When logging is turned on, then copy output to logfile\r
+                {\r
+                    write(fdlogfile, buffer, realsize);\r
+                }\r
+            }\r
+\r
+            // check for keypress, and write any out the port.\r
+            if (kbhit())\r
+            {\r
+                ch = getch();\r
+                if (ch == 0x1b)\r
+                {\r
+                    break;\r
+                }\r
+                buffer[0] = (unsigned char)ch;\r
+                buffer[1] = 0;\r
+\r
+                if (IspEnvironment->LocalEcho)\r
+                {\r
+                    write(1, buffer, 1);\r
+                }\r
+\r
+                SendComPort(IspEnvironment, buffer);\r
+            }\r
+        }\r
+        while (ch != 0x1b);\r
+\r
+        DebugPrintf(1, "\n\nTerminal stopped\n\n");\r
+        fflush(stdout);\r
+\r
+        ResetKeyboardTtySettings();\r
+\r
+        if (IspEnvironment->LogFile)\r
+        {\r
+            close(fdlogfile);\r
+        }\r
+    }\r
+}\r
+#endif\r
diff --git a/host/app/lpc21lisp/lpcterm.h b/host/app/lpc21lisp/lpcterm.h
new file mode 100644 (file)
index 0000000..3fda95d
--- /dev/null
@@ -0,0 +1,43 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          lpcterm.h\r
+\r
+Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+                   GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+    This file is part of lpc21isp.\r
+\r
+    lpc21isp is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    any later version.\r
+\r
+    lpc21isp is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    and GNU General Public License along with lpc21isp.\r
+    If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#ifndef TRUE\r
+#define TRUE (1)\r
+#endif\r
+#ifndef FALSE\r
+#define FALSE (0)\r
+#endif\r
+\r
+typedef int BOOL;\r
+\r
+void Terminal(ISP_ENVIRONMENT *IspEnvironment);\r
+BOOL CheckTerminalParameters(ISP_ENVIRONMENT *IspEnvironment, char* pstr);\r
index a10eb74ae53bfdc7c45f10eed567ec5fd0fc53fe..1f47def0be6b15b945db34e46722e2a451f50db0 100644 (file)
@@ -2,6 +2,7 @@ LN_HEADERS=y
 
 CONFIG_APP_ROCON_CMD=y
 CONFIG_APP_USB_SENDHEX=y
+CONFIG_APP_LPC21LISP=y
 
 # Fails
 CONFIG_OC_ULUT=n