]> rtime.felk.cvut.cz Git - sysless.git/blobdiff - arch/arm/mach-lpc21xx/tools/lpc21isp/lpcprog.c
Added newer version (1.64) of lpc21isp
[sysless.git] / arch / arm / mach-lpc21xx / tools / lpc21isp / lpcprog.c
diff --git a/arch/arm/mach-lpc21xx/tools/lpc21isp/lpcprog.c b/arch/arm/mach-lpc21xx/tools/lpc21isp/lpcprog.c
new file mode 100644 (file)
index 0000000..ef5f39e
--- /dev/null
@@ -0,0 +1,1148 @@
+/******************************************************************************\r
+\r
+Project:           Portable command line ISP for Philips LPC2000 family\r
+                   and Analog Devices ADUC70xx\r
+\r
+Filename:          lpcprog.c\r
+\r
+Compiler:          Microsoft VC 6/7, GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright:         (c) Martin Maurer 2003-2008, 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
+#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
+static int unsigned SectorTable_RAM[]  = { 65000 };\r
+\r
+static LPC_DEVICE_TYPE LPCtypes[] =\r
+{\r
+    { 0, 0, 0 },  /* unknown */\r
+    { 0x0004FF11, 2103,  32,  8,  8, 4096, SectorTable_2103 },\r
+    { 0xFFF0FF12, 2104, 128, 16, 15, 8192, SectorTable_210x },\r
+    { 0xFFF0FF22, 2105, 128, 32, 15, 8192, SectorTable_210x },\r
+    { 0xFFF0FF32, 2106, 128, 64, 15, 8192, SectorTable_210x },\r
+    { 0x0201FF01, 2109,  64,  8,  8, 4096, SectorTable_2109 },\r
+    { 0x0101FF12, 2114, 128, 16, 15, 8192, SectorTable_211x },\r
+    { 0x0201FF12, 2119, 128, 16, 15, 8192, SectorTable_211x },\r
+    { 0x0101FF13, 2124, 256, 16, 17, 8192, SectorTable_212x },\r
+    { 0x0201FF13, 2129, 256, 16, 17, 8192, SectorTable_212x },\r
+    { 0x0002FF01, 2131,  32,  8,  8, 4096, SectorTable_213x },\r
+    { 0x0002FF11, 2132,  64, 16,  9, 4096, SectorTable_213x },\r
+    { 0x0002FF12, 2134, 128, 16, 11, 4096, SectorTable_213x },\r
+    { 0x0002FF23, 2136, 256, 32, 15, 4096, SectorTable_213x },\r
+    { 0x0002FF25, 2138, 512, 32, 27, 4096, SectorTable_213x },\r
+    { 0x0402FF01, 2141,  32,  8,  8, 4096, SectorTable_213x },\r
+    { 0x0402FF11, 2142,  64, 16,  9, 4096, SectorTable_213x },\r
+    { 0x0402FF12, 2144, 128, 16, 11, 4096, SectorTable_213x },\r
+    { 0x0402FF23, 2146, 256, 40, 15, 4096, SectorTable_213x },\r
+    { 0x0402FF25, 2148, 512, 40, 27, 4096, SectorTable_213x },\r
+    { 0x0301FF13, 2194, 256, 16, 17, 8192, SectorTable_212x },\r
+    { 0x0301FF12, 2210,   0, 16,  0, 8192, SectorTable_211x }, /* table is a "don't care" */\r
+    { 0x0401FF12, 2212, 128, 16, 15, 8192, SectorTable_211x },\r
+    { 0x0601FF13, 2214, 256, 16, 17, 8192, SectorTable_212x },\r
+    /*            2290; same id as the LPC2210 */\r
+    { 0x0401FF13, 2292, 256, 16, 17, 8192, SectorTable_212x },\r
+    { 0x0501FF13, 2294, 256, 16, 17, 8192, SectorTable_212x },\r
+    { 0x00000000, 2361, 128, 34, 11, 4096, SectorTable_213x },\r
+    { 0x00000000, 2362, 128, 34, 11, 4096, SectorTable_213x },\r
+    { 0x1600F902, 2364, 128, 34, 11, 4096, SectorTable_213x },\r
+    { 0x1600E823, 2365, 256, 58, 15, 4096, SectorTable_213x },\r
+    { 0x1600F923, 2366, 256, 58, 15, 4096, SectorTable_213x },\r
+    { 0x1600E825, 2367, 512, 58, 15, 4096, SectorTable_213x },\r
+    { 0x1600F925, 2368, 512, 58, 28, 4096, SectorTable_213x },\r
+    { 0x1700E825, 2377, 512, 58, 28, 4096, SectorTable_213x },\r
+    { 0x1700FD25, 2378, 512, 58, 28, 4096, SectorTable_213x },\r
+    { 0x1800F935, 2387, 512, 98, 28, 4096, SectorTable_213x },\r
+    { 0x1800FF35, 2388, 512, 98, 28, 4096, SectorTable_213x },\r
+    { 0x1500FF35, 2458, 512, 98, 28, 4096, SectorTable_213x },\r
+    { 0x1600FF30, 2460,   0, 98,  0, 4096, SectorTable_213x },\r
+    { 0x1600FF35, 2468, 512, 98, 28, 4096, SectorTable_213x },\r
+    { 0x1701FF30, 2470,   0, 98,  0, 4096, SectorTable_213x },\r
+    { 0x1701FF35, 2478, 512, 98, 28, 4096, SectorTable_213x }\r
+};\r
+\r
+/***************************** PHILIPS Download *********************************/\r
+/**  Download the file from the internal memory image to the philips microcontroller.\r
+*   This function is visible from outside if COMPILE_FOR_LPC21\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
+\r
+    SendComPort(IspEnvironment, Command);\r
+    ReceiveComPort(IspEnvironment, AnswerBuffer, AnswerLength - 1, &realsize, 2, 5000);\r
+    cmdlen = strlen(Command);\r
+    return (strncmp(AnswerBuffer, Command, cmdlen) == 0\r
+        && strcmp(AnswerBuffer + cmdlen, "0\r\n") == 0);\r
+}\r
+\r
+\r
+\r
+/***************************** PhilipsOutputErrorMessage ***********************/\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 PhilipsOutputErrorMessage(in)        // Cleanly remove this feature from the embedded version !!\r
+\r
+#else\r
+\r
+static void PhilipsOutputErrorMessage(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  PhilipsOutputErrorMessage() 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
+    PhilipsOutputErrorMessage(Result);\r
+\r
+    return Result;\r
+}\r
+\r
+\r
+int PhilipsDownload(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+    unsigned long realsize;\r
+    char Answer[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 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
+    long WatchDogSeconds = 0;\r
+    int WaitForWatchDog = 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
+    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
+        // 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
+\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 < 100; 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=%ld): '", strippedsize);\r
+            DumpString(3, strippedAnswer, strippedsize, tmp_string);\r
+\r
+            if (strcmp(strippedAnswer, "Bootloader\r\n") == 0 && IspEnvironment->TerminalOnly == 0)\r
+            {\r
+                long chars, xtal;\r
+                unsigned long ticks;\r
+                chars = (17 * IspEnvironment->BinaryLength + 1) / 10;\r
+                WatchDogSeconds = (10 * chars + 5) / atol(IspEnvironment->baud_rate) + 10;\r
+                xtal = atol(IspEnvironment->StringOscillator) * 1000;\r
+                ticks = (unsigned long)WatchDogSeconds * ((xtal + 15) / 16);\r
+                DebugPrintf(2, "Entering ISP; re-synchronizing (watchdog = %ld seconds)\n", WatchDogSeconds);\r
+                sprintf(temp, "T %lu\r\n", ticks);\r
+                SendComPort(IspEnvironment, temp);\r
+                ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,100);\r
+                if (strcmp(Answer, "OK\r\n") != 0)\r
+                {\r
+                    ResetKeyboardTtySettings();\r
+                    DebugPrintf(2, "No answer on 'watchdog timer set'\n");\r
+                    return (NO_ANSWER_WDT);\r
+                }\r
+                SendComPort(IspEnvironment, "G 10356\r\n");\r
+                Sleep(200);\r
+                nQuestionMarks = 0;\r
+                WaitForWatchDog = 1;\r
+                continue;\r
+            }\r
+\r
+            tStartUpload = time(NULL);\r
+\r
+            if (strcmp(strippedAnswer, "Synchronized\r\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
+    if (IspEnvironment->HalfDuplex == 0)\r
+    {\r
+        SendComPort(IspEnvironment, "Synchronized\r\n");\r
+    }\r
+    else\r
+    {\r
+        SendComPort(IspEnvironment, "Synchronized\n");\r
+    }\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer) - 1, &realsize, 2, 1000);\r
+\r
+    if ((strcmp(Answer, "Synchronized\r\nOK\r\n") != 0) && (strcmp(Answer, "Synchronized\rOK\r\n") != 0) &&\r
+        (strcmp(Answer, "Synchronized\nOK\r\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
+    if (IspEnvironment->HalfDuplex == 0)\r
+        sprintf(temp, "%s\r\n", IspEnvironment->StringOscillator);\r
+    else\r
+        sprintf(temp, "%s\n", IspEnvironment->StringOscillator);\r
+\r
+    SendComPort(IspEnvironment, temp);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 1000);\r
+\r
+    if (IspEnvironment->HalfDuplex == 0)\r
+        sprintf(temp, "%s\r\nOK\r\n", IspEnvironment->StringOscillator);\r
+    else\r
+        sprintf(temp, "%s\nOK\r\n", IspEnvironment->StringOscillator);\r
+\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
+    if (IspEnvironment->HalfDuplex == 0)\r
+        cmdstr = "U 23130\r\n";\r
+    else\r
+        cmdstr = "U 23130\n";\r
+\r
+    //if (!SendAndVerify(IspEnvironment, "U 23130\n", Answer, sizeof Answer))//if (!SendAndVerify(IspEnvironment, "U 23130\r\n", Answer, sizeof Answer))\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
+    if (IspEnvironment->HalfDuplex == 0)\r
+        cmdstr = "K\r\n";\r
+    else\r
+        cmdstr = "K\n";\r
+\r
+    SendComPort(IspEnvironment, cmdstr);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 4,5000);\r
+\r
+\r
+    //if (strncmp(Answer, "K\n", 2) != 0)//if (strncmp(Answer, "K\r\n", 3) != 0)\r
+    if (strncmp(Answer, cmdstr, strlen(cmdstr)) != 0)\r
+    {\r
+        DebugPrintf(1, "no answer on Read Boot Code Version\n");\r
+        return (NO_ANSWER_RBV);\r
+    }\r
+\r
+    //if (strncmp(Answer, "K\n0\r\n", 5) == 0)//if (strncmp(Answer, "K\r\n0\r\n", 6) == 0)\r
+    if (strncmp(Answer + strlen(cmdstr), "0\r\n", 3) == 0)\r
+    {\r
+        strippedAnswer = Answer + strlen(cmdstr) + 3;\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
+    if (IspEnvironment->HalfDuplex == 0)\r
+        cmdstr = "J\r\n";\r
+    else\r
+        cmdstr = "J\n";\r
+\r
+    SendComPort(IspEnvironment, cmdstr);\r
+\r
+    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 3,5000);\r
+\r
+\r
+\r
+    //if (strncmp(Answer, "J\n", 2) != 0)//if (strncmp(Answer, "J\r\n", 3) != 0)\r
+    if (strncmp(Answer, cmdstr, strlen(cmdstr)) != 0)\r
+    {\r
+        DebugPrintf(1, "no answer on Read Part Id\n");\r
+        return (NO_ANSWER_RPID);\r
+    }\r
+\r
+    if (IspEnvironment->HalfDuplex == 0)\r
+        strippedAnswer = (strncmp(Answer, "J\r\n0\r\n", 6) == 0) ? Answer + 6 : Answer;\r
+    else\r
+        strippedAnswer = (strncmp(Answer, "J\n0\r\n", 5) == 0) ? Answer + 5 : Answer;\r
+\r
+    Pos = strtoul(strippedAnswer, &endPtr, 10);\r
+    *endPtr = '\0'; /* delete \r\n */\r
+    for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && LPCtypes[i].id != Pos; i--)\r
+        /* nothing */;\r
+        IspEnvironment->DetectedDevice = i;\r
+    if (IspEnvironment->DetectedDevice == 0) {\r
+        DebugPrintf(2, "unknown");\r
+    }\r
+    else {\r
+        DebugPrintf(2, "LPC%d, %d kiB ROM / %d kiB SRAM",\r
+            LPCtypes[IspEnvironment->DetectedDevice].Product,\r
+            LPCtypes[IspEnvironment->DetectedDevice].FlashSize,\r
+            LPCtypes[IspEnvironment->DetectedDevice].RAMSize);\r
+    }\r
+    DebugPrintf(2, " (0x%X)\n", Pos);//strippedAnswer);\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 >= LPC_RAMSTART)\r
+    {\r
+        LPCtypes[IspEnvironment->DetectedDevice].FlashSectors = 1;\r
+        LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize  = LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024 - (LPC_RAMBASE - LPC_RAMSTART);\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
+\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 (IspEnvironment->HalfDuplex == 0)\r
+          sprintf(tmpString, "P %ld %ld\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+        else\r
+            sprintf(tmpString, "P %ld %ld\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\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 (IspEnvironment->HalfDuplex == 0)\r
+            sprintf(tmpString, "E %ld %ld\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+        else\r
+            sprintf(tmpString, "E %ld %ld\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
+    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 < LPC_RAMSTART) // Skip Erase when running from RAM\r
+        {\r
+            if (IspEnvironment->HalfDuplex == 0)\r
+                sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
+            else\r
+                sprintf(tmpString, "P %ld %ld\n", Sector, Sector);\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)\r
+            {\r
+                if (IspEnvironment->HalfDuplex == 0)\r
+                    sprintf(tmpString, "E %ld %ld\r\n", Sector, Sector);\r
+                else\r
+                    sprintf(tmpString, "E %ld %ld\n", Sector, Sector);\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
+            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 to much to RAM\r
+            // but then we can always use full 45 byte blocks and length is multiple of 4\r
+            CopyLength = SectorChunk;\r
+            if ((CopyLength % (45 * 4)) != 0)\r
+            {\r
+                CopyLength += ((45 * 4) - (CopyLength % (45 * 4)));\r
+            }\r
+\r
+            if (IspEnvironment->HalfDuplex == 0)\r
+                sprintf(tmpString, "W %ld %ld\r\n", LPC_RAMBASE, CopyLength);\r
+            else\r
+                sprintf(tmpString, "W %ld %ld\n", LPC_RAMBASE, 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
+            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 < LPC_RAMSTART)\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
+#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
+                    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
+                            // printf("block_CRC = %ld\n", block_CRC);\r
+\r
+                            if (IspEnvironment->HalfDuplex == 0)\r
+                                sprintf(tmpString, "%ld\r\n", block_CRC);\r
+                            else\r
+                                sprintf(tmpString, "%ld\n", block_CRC);\r
+\r
+                            SendComPort(IspEnvironment, tmpString);\r
+\r
+                            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+                            if (IspEnvironment->HalfDuplex == 0)\r
+                                sprintf(tmpString, "%ld\r\nOK\r\n", block_CRC);\r
+                            else\r
+                                sprintf(tmpString, "%ld\nOK\r\n", block_CRC);\r
+\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
+                        // printf("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\r\nOK\r\n", block_CRC);\r
+                        if (strcmp(Answer, tmpString) != 0)\r
+                        {\r
+                            DebugPrintf(1, "Error on writing block_CRC (1)\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
+                    if (IspEnvironment->HalfDuplex == 0)\r
+                        sprintf(tmpString, "%ld\r\n", block_CRC);\r
+                    else\r
+                        sprintf(tmpString, "%ld\n", block_CRC);\r
+\r
+                    SendComPort(IspEnvironment, tmpString);\r
+\r
+                    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+                    if (IspEnvironment->HalfDuplex == 0)\r
+                        sprintf(tmpString, "%ld\r\nOK\r\n", block_CRC);\r
+                    else\r
+                        sprintf(tmpString, "%ld\nOK\r\n", block_CRC);\r
+\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 (2)\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\r\nOK\r\n", block_CRC);\r
+                if (strcmp(Answer, tmpString) != 0)\r
+                {\r
+                    DebugPrintf(1, "Error on writing block_CRC (2)\n");\r
+                    return (ERROR_WRITE_CRC2);\r
+                }\r
+#endif\r
+            }\r
+\r
+            if (IspEnvironment->BinaryOffset < LPC_RAMSTART)\r
+            {\r
+                // Prepare command must be repeated before every write\r
+                if (IspEnvironment->HalfDuplex == 0)\r
+                    sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
+                else\r
+                    sprintf(tmpString, "P %ld %ld\n", Sector, Sector);\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
+                if (IspEnvironment->HalfDuplex == 0)\r
+                    sprintf(tmpString, "C %ld %ld %ld\r\n", SectorStart + SectorOffset, LPC_RAMBASE, CopyLength);\r
+                else\r
+                    sprintf(tmpString, "C %ld %ld %ld\n", SectorStart + SectorOffset, LPC_RAMBASE, 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
+                        if (IspEnvironment->HalfDuplex == 0)\r
+                            sprintf(tmpString, "M %ld %ld %ld\r\n", 64, LPC_RAMBASE + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));\r
+                        else\r
+                            sprintf(tmpString, "M %ld %ld %ld\n", 64, LPC_RAMBASE + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));\r
+                    }\r
+                    else\r
+                    {\r
+                        if (IspEnvironment->HalfDuplex == 0)\r
+                            sprintf(tmpString, "M %ld %ld %ld\r\n", SectorStart + SectorOffset, LPC_RAMBASE, CopyLength);\r
+                        else\r
+                            sprintf(tmpString, "M %ld %ld %ld\n", SectorStart + SectorOffset, LPC_RAMBASE, 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
+    if (WaitForWatchDog)\r
+    {\r
+        DebugPrintf(2, "Wait for restart, in %d seconds from now\n", WatchDogSeconds - (tDoneUpload - tStartUpload));\r
+    }\r
+    else\r
+    {\r
+        DebugPrintf(2, "Now launching the brand new code\n");\r
+        fflush(stdout);\r
+\r
+        if (IspEnvironment->HalfDuplex == 0)\r
+            sprintf(tmpString, "G %ld A\r\n", IspEnvironment->StartAddress);\r
+        else\r
+            sprintf(tmpString, "G %ld A\n", IspEnvironment->StartAddress);\r
+\r
+        SendComPort(IspEnvironment, tmpString); //goto 0 : run this fresh new downloaded code code\r
+        if (IspEnvironment->BinaryOffset < LPC_RAMSTART)\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 (IspEnvironment->HalfDuplex == 0)\r
+            {\r
+                // This was not working with my LPC2214 most of the time - Herbert Demmel\r
+                // was: cmdstr = "G 0 A\r\n0\r";\r
+                cmdstr = "G 0 A\r\n0";\r
+            }\r
+            else\r
+            {\r
+                cmdstr = "G 0 A\n0\r";\r
+            }\r
+\r
+            //if (realsize == 0 || strncmp((const char *)Answer, "G 0 A\n0\r", 8) != 0)//if (realsize == 0 || strncmp((const char *)Answer, "G 0 A\r\n0\r", 9) != 0)\r
+            if (realsize == 0 || strncmp((const char *)Answer, cmdstr, strlen(cmdstr)) != 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