root/trunk/tools/lpc21isp/lpcprog.c

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

Update lpc21isp

Line 
1/******************************************************************************
2
3Project:           Portable command line ISP for Philips LPC2000 family
4                   and Analog Devices ADUC70xx
5
6Filename:          lpcprog.c
7
8Compiler:          Microsoft VC 6/7, GCC Cygwin, GCC Linux, GCC ARM ELF
9
10Author:            Martin Maurer (Martin.Maurer@clibb.de)
11
12Copyright:         (c) Martin Maurer 2003-2008, All rights reserved
13Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com
14
15    This file is part of lpc21isp.
16
17    lpc21isp is free software: you can redistribute it and/or modify
18    it under the terms of the GNU Lesser General Public License as published by
19    the Free Software Foundation, either version 3 of the License, or
20    any later version.
21
22    lpc21isp is distributed in the hope that it will be useful,
23    but WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25    GNU Lesser General Public License for more details.
26
27    You should have received a copy of the GNU Lesser General Public License
28    and GNU General Public License along with lpc21isp.
29    If not, see <http://www.gnu.org/licenses/>.
30*/
31
32// This file is for the Actual Programming of the LPC Chips
33
34#if defined(_WIN32)
35#if !defined __BORLANDC__
36#include "StdAfx.h"
37#endif
38#endif // defined(_WIN32)
39#include "lpc21isp.h"
40
41#ifdef LPC_SUPPORT
42#include "lpcprog.h"
43
44static const unsigned int SectorTable_210x[] =
45{
46    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
47    8192, 8192, 8192, 8192, 8192, 8192, 8192
48};
49
50static const unsigned int SectorTable_2103[] =
51{
52    4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096
53};
54
55static const unsigned int SectorTable_2109[] =
56{
57    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192
58};
59
60static const unsigned int SectorTable_211x[] =
61{
62    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
63    8192, 8192, 8192, 8192, 8192, 8192, 8192,
64};
65
66static const unsigned int SectorTable_212x[] =
67{
68    8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
69    65536, 65536, 8192, 8192, 8192, 8192, 8192, 8192, 8192
70};
71
72// Used for devices with 500K (LPC2138 and LPC2148) and
73// for devices with 504K (1 extra 4k block at the end)
74static const unsigned int SectorTable_213x[] =
75{
76     4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,
77    32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
78    32768, 32768, 32768, 32768, 32768, 32768,  4096,  4096,
79     4096,  4096,  4096,  4096
80};
81
82static int unsigned SectorTable_RAM[]  = { 65000 };
83
84static LPC_DEVICE_TYPE LPCtypes[] =
85{
86    { 0, 0, 0 },  /* unknown */
87    { 0x0004FF11, 2103,  32,  8,  8, 4096, SectorTable_2103 },
88    { 0xFFF0FF12, 2104, 128, 16, 15, 8192, SectorTable_210x },
89    { 0xFFF0FF22, 2105, 128, 32, 15, 8192, SectorTable_210x },
90    { 0xFFF0FF32, 2106, 128, 64, 15, 8192, SectorTable_210x },
91    { 0x0201FF01, 2109,  64,  8,  8, 4096, SectorTable_2109 },
92    { 0x0101FF12, 2114, 128, 16, 15, 8192, SectorTable_211x },
93    { 0x0201FF12, 2119, 128, 16, 15, 8192, SectorTable_211x },
94    { 0x0101FF13, 2124, 256, 16, 17, 8192, SectorTable_212x },
95    { 0x0201FF13, 2129, 256, 16, 17, 8192, SectorTable_212x },
96    { 0x0002FF01, 2131,  32,  8,  8, 4096, SectorTable_213x },
97    { 0x0002FF11, 2132,  64, 16,  9, 4096, SectorTable_213x },
98    { 0x0002FF12, 2134, 128, 16, 11, 4096, SectorTable_213x },
99    { 0x0002FF23, 2136, 256, 32, 15, 4096, SectorTable_213x },
100    { 0x0002FF25, 2138, 512, 32, 27, 4096, SectorTable_213x },
101    { 0x0402FF01, 2141,  32,  8,  8, 4096, SectorTable_213x },
102    { 0x0402FF11, 2142,  64, 16,  9, 4096, SectorTable_213x },
103    { 0x0402FF12, 2144, 128, 16, 11, 4096, SectorTable_213x },
104    { 0x0402FF23, 2146, 256, 40, 15, 4096, SectorTable_213x },
105    { 0x0402FF25, 2148, 512, 40, 27, 4096, SectorTable_213x },
106    { 0x0301FF13, 2194, 256, 16, 17, 8192, SectorTable_212x },
107    { 0x0301FF12, 2210,   0, 16,  0, 8192, SectorTable_211x }, /* table is a "don't care" */
108    { 0x0401FF12, 2212, 128, 16, 15, 8192, SectorTable_211x },
109    { 0x0601FF13, 2214, 256, 16, 17, 8192, SectorTable_212x },
110    /*            2290; same id as the LPC2210 */
111    { 0x0401FF13, 2292, 256, 16, 17, 8192, SectorTable_212x },
112    { 0x0501FF13, 2294, 256, 16, 17, 8192, SectorTable_212x },
113    { 0x00000000, 2361, 128, 34, 11, 4096, SectorTable_213x },
114    { 0x00000000, 2362, 128, 34, 11, 4096, SectorTable_213x },
115    { 0x1600F902, 2364, 128, 34, 11, 4096, SectorTable_213x },
116    { 0x1600E823, 2365, 256, 58, 15, 4096, SectorTable_213x },
117    { 0x1600F923, 2366, 256, 58, 15, 4096, SectorTable_213x },
118    { 0x1600E825, 2367, 512, 58, 15, 4096, SectorTable_213x },
119    { 0x1600F925, 2368, 512, 58, 28, 4096, SectorTable_213x },
120    { 0x1700E825, 2377, 512, 58, 28, 4096, SectorTable_213x },
121    { 0x1700FD25, 2378, 512, 58, 28, 4096, SectorTable_213x },
122    { 0x1800F935, 2387, 512, 98, 28, 4096, SectorTable_213x },
123    { 0x1800FF35, 2388, 512, 98, 28, 4096, SectorTable_213x },
124    { 0x1500FF35, 2458, 512, 98, 28, 4096, SectorTable_213x },
125    { 0x1600FF30, 2460,   0, 98,  0, 4096, SectorTable_213x },
126    { 0x1600FF35, 2468, 512, 98, 28, 4096, SectorTable_213x },
127    { 0x1701FF30, 2470,   0, 98,  0, 4096, SectorTable_213x },
128    { 0x1701FF35, 2478, 512, 98, 28, 4096, SectorTable_213x }
129};
130
131/***************************** PHILIPS Download *********************************/
132/**  Download the file from the internal memory image to the philips microcontroller.
133*   This function is visible from outside if COMPILE_FOR_LPC21
134*/
135
136static int SendAndVerify(ISP_ENVIRONMENT *IspEnvironment, const char *Command,
137                                 char *AnswerBuffer, int AnswerLength)
138{
139    unsigned long realsize;
140    int cmdlen;
141
142    SendComPort(IspEnvironment, Command);
143    ReceiveComPort(IspEnvironment, AnswerBuffer, AnswerLength - 1, &realsize, 2, 5000);
144    cmdlen = strlen(Command);
145    return (strncmp(AnswerBuffer, Command, cmdlen) == 0
146        && strcmp(AnswerBuffer + cmdlen, "0\r\n") == 0);
147}
148
149
150
151/***************************** PhilipsOutputErrorMessage ***********************/
152/**  Given an error number find and print the appropriate error message.
153\param [in] ErrorNumber The number of the error.
154*/
155#if defined COMPILE_FOR_LPC21
156
157#define PhilipsOutputErrorMessage(in)        // Cleanly remove this feature from the embedded version !!
158
159#else
160
161static void PhilipsOutputErrorMessage(unsigned char ErrorNumber)
162{
163    switch (ErrorNumber)
164    {
165    case   0:
166        DebugPrintf(1, "CMD_SUCCESS\n");
167        break;
168
169    case   1:
170        DebugPrintf(1, "INVALID_COMMAND\n");
171        break;
172
173    case   2:
174        DebugPrintf(1, "SRC_ADDR_ERROR: Source address is not on word boundary.\n");
175        break;
176    case   3:
177        DebugPrintf(1, "DST_ADDR_ERROR: Destination address is not on a correct boundary.\n");
178        break;
179
180    case   4:
181        DebugPrintf(1, "SRC_ADDR_NOT_MAPPED: Source address is not mapped in the memory map.\n"
182                       "                     Count value is taken into consideration where applicable.\n");
183        break;
184
185    case   5:
186        DebugPrintf(1, "DST_ADDR_NOT_MAPPED: Destination address is not mapped in the memory map.\n"
187                       "                     Count value is taken into consideration where applicable.\n");
188        break;
189
190    case   6:
191        DebugPrintf(1, "COUNT_ERROR: Byte count is not multiple of 4 or is not a permitted value.\n");
192        break;
193
194    case   7:
195        DebugPrintf(1, "INVALID_SECTOR: Sector number is invalid or end sector number is\n"
196                       "                greater than start sector number.\n");
197        break;
198
199    case   8:
200        DebugPrintf(1, "SECTOR_NOT_BLANK\n");
201        break;
202
203    case   9:
204        DebugPrintf(1, "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION:\n"
205                       "Command to prepare sector for write operation was not executed.\n");
206        break;
207
208    case  10:
209        DebugPrintf(1, "COMPARE_ERROR: Source and destination data not equal.\n");
210        break;
211
212    case  11:
213        DebugPrintf(1, "BUSY: Flash programming hardware interface is busy.\n");
214        break;
215
216    case  12:
217        DebugPrintf(1, "PARAM_ERROR: Insufficient number of parameters or invalid parameter.\n");
218        break;
219
220    case  13:
221        DebugPrintf(1, "ADDR_ERROR: Address is not on word boundary.\n");
222        break;
223
224    case  14:
225        DebugPrintf(1, "ADDR_NOT_MAPPED: Address is not mapped in the memory map.\n"
226                       "                 Count value is taken in to consideration where applicable.\n");
227        break;
228
229    case  15:
230        DebugPrintf(1, "CMD_LOCKED\n");
231        break;
232
233    case  16:
234        DebugPrintf(1, "INVALID_CODE: Unlock code is invalid.\n");
235        break;
236
237    case  17:
238        DebugPrintf(1, "INVALID_BAUD_RATE: Invalid baud rate setting.\n");
239        break;
240
241    case  18:
242        DebugPrintf(1, "INVALID_STOP_BIT: Invalid stop bit setting.\n");
243        break;
244
245    case  19:
246        DebugPrintf( 1, "CODE READ PROTECTION ENABLED\n");
247        break;
248
249    case 255:
250        break;
251
252    default:
253        DebugPrintf(1, "unknown error %u\n", ErrorNumber);
254        break;
255    }
256
257    //DebugPrintf(1, "error (%u), see  PhilipsOutputErrorMessage() in lpc21isp.c for help \n\r", ErrorNumber);
258}
259#endif // !defined COMPILE_FOR_LPC21
260
261/***************************** GetAndReportErrorNumber ***************************/
262/**  Find error number in string.  This will normally be the string
263returned from the microcontroller.
264\param [in] Answer the buffer to search for the error number.
265\return the error number found, if no linefeed found before the end of the
266string an error value of 255 is returned. If a non-numeric value is found
267then it is printed to stdout and an error value of 255 is returned.
268*/
269static unsigned char GetAndReportErrorNumber(const char *Answer)
270{
271    unsigned char Result = 0xFF;                            // Error !!!
272    unsigned int i = 0;
273
274    while (1)
275    {
276        if (Answer[i] == 0x00)
277        {
278            break;
279        }
280
281        if (Answer[i] == 0x0a)
282        {
283            i++;
284
285            if (Answer[i] < '0' || Answer[i] > '9')
286            {
287                DebugPrintf(1, "ErrorString: %s", &Answer[i]);
288                break;
289            }
290
291            Result = (unsigned char) (atoi(&Answer[i]));
292            break;
293        }
294
295        i++;
296    }
297
298    PhilipsOutputErrorMessage(Result);
299
300    return Result;
301}
302
303
304int PhilipsDownload(ISP_ENVIRONMENT *IspEnvironment)
305{
306    unsigned long realsize;
307    char Answer[128];
308    char temp[128];
309    /*const*/ char *strippedAnswer, *endPtr;
310    int  strippedsize;
311    int nQuestionMarks;
312    int found;
313    unsigned long Sector;
314    unsigned long SectorLength;
315    unsigned long SectorStart, SectorOffset, SectorChunk;
316    char tmpString[128];
317    char uuencode_table[64];
318    int Line;
319    unsigned long tmpStringPos;
320    unsigned long BlockOffset;
321    unsigned long Block;
322    unsigned long Pos;
323    unsigned long CopyLength;
324    int c,k=0,i;
325    unsigned long ivt_CRC;          // CRC over interrupt vector table
326    unsigned long block_CRC;
327    time_t tStartUpload=0, tDoneUpload=0;
328    long WatchDogSeconds = 0;
329    int WaitForWatchDog = 0;
330    char tmp_string[64];
331    char * cmdstr;
332
333#if !defined COMPILE_FOR_LPC21
334
335#if defined __BORLANDC__
336#define local_static static
337#else
338#define local_static
339#endif
340
341//    char * cmdstr;
342    int repeat = 0;
343    // Puffer for data to resend after "RESEND\r\n" Target responce
344    local_static char sendbuf0[128];
345    local_static char sendbuf1[128];
346    local_static char sendbuf2[128];
347    local_static char sendbuf3[128];
348    local_static char sendbuf4[128];
349    local_static char sendbuf5[128];
350    local_static char sendbuf6[128];
351    local_static char sendbuf7[128];
352    local_static char sendbuf8[128];
353    local_static char sendbuf9[128];
354    local_static char sendbuf10[128];
355    local_static char sendbuf11[128];
356    local_static char sendbuf12[128];
357    local_static char sendbuf13[128];
358    local_static char sendbuf14[128];
359    local_static char sendbuf15[128];
360    local_static char sendbuf16[128];
361    local_static char sendbuf17[128];
362    local_static char sendbuf18[128];
363    local_static char sendbuf19[128];
364
365    char * sendbuf[20] = {    sendbuf0,  sendbuf1,  sendbuf2,  sendbuf3,  sendbuf4,
366                              sendbuf5,  sendbuf6,  sendbuf7,  sendbuf8,  sendbuf9,
367                              sendbuf10, sendbuf11, sendbuf12, sendbuf13, sendbuf14,
368                              sendbuf15, sendbuf16, sendbuf17, sendbuf18, sendbuf19};
369#endif
370
371    if (!IspEnvironment->DetectOnly)
372    {
373        // Build up uuencode table
374        uuencode_table[0] = 0x60;           // 0x20 is translated to 0x60 !
375
376        for (i = 1; i < 64; i++)
377        {
378            uuencode_table[i] = (char)(0x20 + i);
379        }
380
381        // Patch 0x14, otherwise it is not running and jumps to boot mode
382
383        ivt_CRC = 0;
384
385        // Clear the vector at 0x14 so it doesn't affect the checksum:
386        for (i = 0; i < 4; i++)
387        {
388            IspEnvironment->BinaryContent[i + 0x14] = 0;
389        }
390
391        // Calculate a native checksum of the little endian vector table:
392        for (i = 0; i < (4 * 8);) {
393            ivt_CRC += IspEnvironment->BinaryContent[i++];
394            ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;
395            ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;
396            ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;
397        }
398
399        /* Negate the result and place in the vector at 0x14 as little endian
400        * again. The resulting vector table should checksum to 0. */
401        ivt_CRC = (unsigned long) (0 - ivt_CRC);
402        for (i = 0; i < 4; i++)
403        {
404            IspEnvironment->BinaryContent[i + 0x14] = (unsigned char)(ivt_CRC >> (8 * i));
405        }
406
407        DebugPrintf(3, "Position 0x14 patched: ivt_CRC = 0x%08lX\n", ivt_CRC);
408    }
409
410    DebugPrintf(2, "Synchronizing (ESC to abort)");
411
412    PrepareKeyboardTtySettings();
413
414#if defined INTEGRATED_IN_WIN_APP
415    if (IspEnvironment->NoSync)
416    {
417        found = 1;
418    }
419    else
420#endif
421    {
422        for (nQuestionMarks = found = 0; !found && nQuestionMarks < 100; nQuestionMarks++)
423        {
424#if defined INTEGRATED_IN_WIN_APP
425            // allow calling application to abort when syncing takes too long
426
427            if (!AppSyncing(nQuestionMarks))
428            {
429                return (USER_ABORT_SYNC);
430            }
431#else
432#ifndef Exclude_kbhit
433            if (kbhit())
434            {
435                if (getch() == 0x1b)
436                {
437                    ResetKeyboardTtySettings();
438                    DebugPrintf(2, "\nUser aborted during synchronisation\n");
439                    return (USER_ABORT_SYNC);
440                }
441            }
442#endif
443#endif
444
445            DebugPrintf(2, ".");
446            SendComPort(IspEnvironment, "?");
447
448            memset(Answer,0,sizeof(Answer));
449            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,100);
450
451            strippedAnswer = Answer;
452            strippedsize = realsize;
453            while ((strippedsize > 0) && ((*strippedAnswer == '?') || (*strippedAnswer == 0)))
454            {
455                strippedAnswer++;
456                strippedsize--;
457            }
458
459            sprintf(tmp_string, "StrippedAnswer(Length=%ld): '", strippedsize);
460            DumpString(3, strippedAnswer, strippedsize, tmp_string);
461
462            if (strcmp(strippedAnswer, "Bootloader\r\n") == 0 && IspEnvironment->TerminalOnly == 0)
463            {
464                long chars, xtal;
465                unsigned long ticks;
466                chars = (17 * IspEnvironment->BinaryLength + 1) / 10;
467                WatchDogSeconds = (10 * chars + 5) / atol(IspEnvironment->baud_rate) + 10;
468                xtal = atol(IspEnvironment->StringOscillator) * 1000;
469                ticks = (unsigned long)WatchDogSeconds * ((xtal + 15) / 16);
470                DebugPrintf(2, "Entering ISP; re-synchronizing (watchdog = %ld seconds)\n", WatchDogSeconds);
471                sprintf(temp, "T %lu\r\n", ticks);
472                SendComPort(IspEnvironment, temp);
473                ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,100);
474                if (strcmp(Answer, "OK\r\n") != 0)
475                {
476                    ResetKeyboardTtySettings();
477                    DebugPrintf(2, "No answer on 'watchdog timer set'\n");
478                    return (NO_ANSWER_WDT);
479                }
480                SendComPort(IspEnvironment, "G 10356\r\n");
481                Sleep(200);
482                nQuestionMarks = 0;
483                WaitForWatchDog = 1;
484                continue;
485            }
486
487            tStartUpload = time(NULL);
488
489            if (strcmp(strippedAnswer, "Synchronized\r\n") == 0)
490            {
491                found = 1;
492            }
493#if !defined COMPILE_FOR_LPC21
494            else
495            {
496                ResetTarget(IspEnvironment, PROGRAM_MODE);
497            }
498#endif
499        }
500    }
501
502    ResetKeyboardTtySettings();
503
504    if (!found)
505    {
506        DebugPrintf(1, " no answer on '?'\n");
507        return (NO_ANSWER_QM);
508    }
509
510#if defined INTEGRATED_IN_WIN_APP
511    AppSyncing(-1);                         // flag syncing done
512#endif
513
514    DebugPrintf(2, " OK\n");
515
516    if (IspEnvironment->HalfDuplex == 0)
517    {
518        SendComPort(IspEnvironment, "Synchronized\r\n");
519    }
520    else
521    {
522        SendComPort(IspEnvironment, "Synchronized\n");
523    }
524
525    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer) - 1, &realsize, 2, 1000);
526
527    if ((strcmp(Answer, "Synchronized\r\nOK\r\n") != 0) && (strcmp(Answer, "Synchronized\rOK\r\n") != 0) &&
528        (strcmp(Answer, "Synchronized\nOK\r\n") != 0))
529    {
530        DebugPrintf(1, "No answer on 'Synchronized'\n");
531        return (NO_ANSWER_SYNC);
532    }
533
534    DebugPrintf(3, "Synchronized 1\n");
535
536    DebugPrintf(3, "Setting oscillator\n");
537
538    if (IspEnvironment->HalfDuplex == 0)
539        sprintf(temp, "%s\r\n", IspEnvironment->StringOscillator);
540    else
541        sprintf(temp, "%s\n", IspEnvironment->StringOscillator);
542
543    SendComPort(IspEnvironment, temp);
544
545    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 1000);
546
547    if (IspEnvironment->HalfDuplex == 0)
548        sprintf(temp, "%s\r\nOK\r\n", IspEnvironment->StringOscillator);
549    else
550        sprintf(temp, "%s\nOK\r\n", IspEnvironment->StringOscillator);
551
552    if (strcmp(Answer, temp) != 0)
553    {
554        DebugPrintf(1, "No answer on Oscillator-Command\n");
555        return (NO_ANSWER_OSC);
556    }
557
558    DebugPrintf(3, "Unlock\n");
559
560    if (IspEnvironment->HalfDuplex == 0)
561        cmdstr = "U 23130\r\n";
562    else
563        cmdstr = "U 23130\n";
564
565    //if (!SendAndVerify(IspEnvironment, "U 23130\n", Answer, sizeof Answer))//if (!SendAndVerify(IspEnvironment, "U 23130\r\n", Answer, sizeof Answer))
566    if (!SendAndVerify(IspEnvironment, cmdstr, Answer, sizeof Answer))
567    {
568        DebugPrintf(1, "Unlock-Command:\n");
569        return (UNLOCK_ERROR + GetAndReportErrorNumber(Answer));
570    }
571
572    DebugPrintf(2, "Read bootcode version: ");
573
574    if (IspEnvironment->HalfDuplex == 0)
575        cmdstr = "K\r\n";
576    else
577        cmdstr = "K\n";
578
579    SendComPort(IspEnvironment, cmdstr);
580
581    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 4,5000);
582
583
584    //if (strncmp(Answer, "K\n", 2) != 0)//if (strncmp(Answer, "K\r\n", 3) != 0)
585    if (strncmp(Answer, cmdstr, strlen(cmdstr)) != 0)
586    {
587        DebugPrintf(1, "no answer on Read Boot Code Version\n");
588        return (NO_ANSWER_RBV);
589    }
590
591    //if (strncmp(Answer, "K\n0\r\n", 5) == 0)//if (strncmp(Answer, "K\r\n0\r\n", 6) == 0)
592    if (strncmp(Answer + strlen(cmdstr), "0\r\n", 3) == 0)
593    {
594        strippedAnswer = Answer + strlen(cmdstr) + 3;
595        /*
596        int maj, min, build;
597        if (sscanf(strippedAnswer, "%d %d %d", &build, &min, &maj) == 2) {
598        maj = min;
599        min = build;
600        build = 0;
601        } // if
602        DebugPrintf(2, "%d.%d.%d\n", maj, min, build);
603        */
604        DebugPrintf(2, strippedAnswer);
605    }
606    else
607    {
608        DebugPrintf(2, "unknown\n");
609    }
610
611    DebugPrintf(2, "Read part ID: ");
612
613    if (IspEnvironment->HalfDuplex == 0)
614        cmdstr = "J\r\n";
615    else
616        cmdstr = "J\n";
617
618    SendComPort(IspEnvironment, cmdstr);
619
620    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 3,5000);
621
622
623
624    //if (strncmp(Answer, "J\n", 2) != 0)//if (strncmp(Answer, "J\r\n", 3) != 0)
625    if (strncmp(Answer, cmdstr, strlen(cmdstr)) != 0)
626    {
627        DebugPrintf(1, "no answer on Read Part Id\n");
628        return (NO_ANSWER_RPID);
629    }
630
631    if (IspEnvironment->HalfDuplex == 0)
632        strippedAnswer = (strncmp(Answer, "J\r\n0\r\n", 6) == 0) ? Answer + 6 : Answer;
633    else
634        strippedAnswer = (strncmp(Answer, "J\n0\r\n", 5) == 0) ? Answer + 5 : Answer;
635
636    Pos = strtoul(strippedAnswer, &endPtr, 10);
637    *endPtr = '\0'; /* delete \r\n */
638    for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && LPCtypes[i].id != Pos; i--)
639        /* nothing */;
640        IspEnvironment->DetectedDevice = i;
641    if (IspEnvironment->DetectedDevice == 0) {
642        DebugPrintf(2, "unknown");
643    }
644    else {
645        DebugPrintf(2, "LPC%d, %d kiB ROM / %d kiB SRAM",
646            LPCtypes[IspEnvironment->DetectedDevice].Product,
647            LPCtypes[IspEnvironment->DetectedDevice].FlashSize,
648            LPCtypes[IspEnvironment->DetectedDevice].RAMSize);
649    }
650    DebugPrintf(2, " (0x%X)\n", Pos);//strippedAnswer);
651
652    /* In case of a download to RAM, use full RAM for downloading
653    * set the flash parameters to full RAM also.
654    * This makes sure that all code is downloaded as one big sector
655    */
656
657    if (IspEnvironment->BinaryOffset >= LPC_RAMSTART)
658    {
659        LPCtypes[IspEnvironment->DetectedDevice].FlashSectors = 1;
660        LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize  = LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024 - (LPC_RAMBASE - LPC_RAMSTART);
661        LPCtypes[IspEnvironment->DetectedDevice].SectorTable  = SectorTable_RAM;
662        SectorTable_RAM[0] = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;
663    }
664    if (IspEnvironment->DetectOnly)
665        return (0);
666
667
668    // Start with sector 1 and go upward... Sector 0 containing the interrupt vectors
669    // will be loaded last, since it contains a checksum and device will re-enter
670    // bootloader mode as long as this checksum is invalid.
671    DebugPrintf(2, "Will start programming at Sector 1 if possible, and conclude with Sector 0 to ensure that checksum is written last.\n");
672    if (LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0] >= IspEnvironment->BinaryLength)
673    {
674        Sector = 0;
675        SectorStart = 0;
676    }
677    else
678    {
679        SectorStart = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0];
680        Sector = 1;
681    }
682
683    if (IspEnvironment->WipeDevice == 1)
684    {
685        DebugPrintf(2, "Wiping Device. ");
686
687        if (IspEnvironment->HalfDuplex == 0)
688          sprintf(tmpString, "P %ld %ld\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);
689        else
690            sprintf(tmpString, "P %ld %ld\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);
691
692        if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
693        {
694            DebugPrintf(1, "Wrong answer on Prepare-Command\n");
695            return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));
696        }
697
698        if (IspEnvironment->HalfDuplex == 0)
699            sprintf(tmpString, "E %ld %ld\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);
700        else
701            sprintf(tmpString, "E %ld %ld\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);
702
703        if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
704        {
705            DebugPrintf(1, "Wrong answer on Erase-Command\n");
706            return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));
707        }
708        DebugPrintf(2, "OK \n");
709    }
710    while (1)
711    {
712        if (Sector >= LPCtypes[IspEnvironment->DetectedDevice].FlashSectors)
713        {
714            DebugPrintf(1, "Program too large; running out of Flash sectors.\n");
715            return (PROGRAM_TOO_LARGE);
716        }
717
718        DebugPrintf(2, "Sector %ld: ", Sector);
719        fflush(stdout);
720
721        if (IspEnvironment->BinaryOffset < LPC_RAMSTART) // Skip Erase when running from RAM
722        {
723            if (IspEnvironment->HalfDuplex == 0)
724                sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);
725            else
726                sprintf(tmpString, "P %ld %ld\n", Sector, Sector);
727
728            if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
729            {
730                DebugPrintf(1, "Wrong answer on Prepare-Command (1) (Sector %ld)\n", Sector);
731                return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));
732            }
733
734            DebugPrintf(2, ".");
735            fflush(stdout);
736            if (IspEnvironment->WipeDevice == 0)
737            {
738                if (IspEnvironment->HalfDuplex == 0)
739                    sprintf(tmpString, "E %ld %ld\r\n", Sector, Sector);
740                else
741                    sprintf(tmpString, "E %ld %ld\n", Sector, Sector);
742
743                if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
744                {
745                    DebugPrintf(1, "Wrong answer on Erase-Command (Sector %ld)\n", Sector);
746                    return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));
747                }
748
749                DebugPrintf(2, ".");
750                fflush(stdout);
751            }
752        }
753
754        SectorLength = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];
755        if (SectorLength > IspEnvironment->BinaryLength - SectorStart)
756        {
757            SectorLength = IspEnvironment->BinaryLength - SectorStart;
758        }
759
760        for (SectorOffset = 0; SectorOffset < SectorLength; SectorOffset += SectorChunk)
761        {
762            if (SectorOffset > 0)
763            {
764                // Add a visible marker between segments in a sector
765                DebugPrintf(2, "|");  /* means: partial segment copied */
766                fflush(stdout);
767            }
768
769            // If the Flash ROM sector size is bigger than the number of bytes
770            // we can copy from RAM to Flash, we must "chop up" the sector and
771            // copy these individually.
772            // This is especially needed in the case where a Flash sector is
773            // bigger than the amount of SRAM.
774            SectorChunk = SectorLength - SectorOffset;
775            if (SectorChunk > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)
776            {
777                SectorChunk = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;
778            }
779
780            // Write multiple of 45 * 4 Byte blocks to RAM, but copy maximum of on sector to Flash
781            // In worst case we transfer up to 180 byte to much to RAM
782            // but then we can always use full 45 byte blocks and length is multiple of 4
783            CopyLength = SectorChunk;
784            if ((CopyLength % (45 * 4)) != 0)
785            {
786                CopyLength += ((45 * 4) - (CopyLength % (45 * 4)));
787            }
788
789            if (IspEnvironment->HalfDuplex == 0)
790                sprintf(tmpString, "W %ld %ld\r\n", LPC_RAMBASE, CopyLength);
791            else
792                sprintf(tmpString, "W %ld %ld\n", LPC_RAMBASE, CopyLength);
793
794            if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
795            {
796                DebugPrintf(1, "Wrong answer on Write-Command\n");
797                return (WRONG_ANSWER_WRIT + GetAndReportErrorNumber(Answer));
798            }
799
800            DebugPrintf(2, ".");
801            fflush(stdout);
802
803            block_CRC = 0;
804            Line = 0;
805
806            // Transfer blocks of 45 * 4 bytes to RAM
807            for (Pos = SectorStart + SectorOffset; (Pos < SectorStart + SectorOffset + CopyLength) && (Pos < IspEnvironment->BinaryLength); Pos += (45 * 4))
808            {
809                for (Block = 0; Block < 4; Block++)  // Each block 45 bytes
810                {
811                    DebugPrintf(2, ".");
812                    fflush(stdout);
813
814#if defined INTEGRATED_IN_WIN_APP
815                    // inform the calling application about having written another chuck of data
816                    AppWritten(45);
817#endif
818
819                    // Uuencode one 45 byte block
820                    tmpStringPos = 0;
821
822#if !defined COMPILE_FOR_LPC21
823                    sendbuf[Line][tmpStringPos++] = (char)(' ' + 45);    // Encode Length of block
824#else
825                    tmpString[tmpStringPos++] = (char)(' ' + 45);        // Encode Length of block
826#endif
827
828                    for (BlockOffset = 0; BlockOffset < 45; BlockOffset++)
829                    {
830                        if (IspEnvironment->BinaryOffset < LPC_RAMSTART)
831                        { // Flash: use full memory
832                            c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset];
833                        }
834                        else
835                        { // RAM: Skip first 0x200 bytes, these are used by the download program in LPC21xx
836                            c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset + 0x200];
837                        }
838
839                        block_CRC += c;
840
841                        k = (k << 8) + (c & 255);
842
843                        if ((BlockOffset % 3) == 2)   // Collecting always 3 Bytes, then do processing in 4 Bytes
844                        {
845#if !defined COMPILE_FOR_LPC21
846                            sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 18) & 63];
847                            sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 12) & 63];
848                            sendbuf[Line][tmpStringPos++] = uuencode_table[(k >>  6) & 63];
849                            sendbuf[Line][tmpStringPos++] = uuencode_table[ k        & 63];
850#else
851                            tmpString[tmpStringPos++] = uuencode_table[(k >> 18) & 63];
852                            tmpString[tmpStringPos++] = uuencode_table[(k >> 12) & 63];
853                            tmpString[tmpStringPos++] = uuencode_table[(k >>  6) & 63];
854                            tmpString[tmpStringPos++] = uuencode_table[ k        & 63];
855#endif
856                        }
857                    }
858
859
860#if !defined COMPILE_FOR_LPC21
861                    sendbuf[Line][tmpStringPos++] = '\r';
862                    sendbuf[Line][tmpStringPos++] = '\n';
863                    sendbuf[Line][tmpStringPos++] = 0;
864
865                    SendComPort(IspEnvironment, sendbuf[Line]);
866                    // receive only for debug proposes
867                    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);
868#else
869                    tmpString[tmpStringPos++] = '\r';
870                    tmpString[tmpStringPos++] = '\n';
871                    tmpString[tmpStringPos++] = 0;
872
873                    SendComPort(IspEnvironment, tmpString);
874                    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);
875                    if (strncmp(Answer, tmpString, tmpStringPos) != 0)
876                    {
877                        DebugPrintf(1, "Error on writing data (1)\n");
878                        return (ERROR_WRITE_DATA);
879                    }
880#endif
881
882                    Line++;
883
884                    DebugPrintf(3, "Line = %d\n", Line);
885
886                    if (Line == 20)
887                    {
888#if !defined COMPILE_FOR_LPC21
889                        for (repeat = 0; repeat < 3; repeat++)
890                        {
891
892                            // printf("block_CRC = %ld\n", block_CRC);
893
894                            if (IspEnvironment->HalfDuplex == 0)
895                                sprintf(tmpString, "%ld\r\n", block_CRC);
896                            else
897                                sprintf(tmpString, "%ld\n", block_CRC);
898
899                            SendComPort(IspEnvironment, tmpString);
900
901                            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);
902
903                            if (IspEnvironment->HalfDuplex == 0)
904                                sprintf(tmpString, "%ld\r\nOK\r\n", block_CRC);
905                            else
906                                sprintf(tmpString, "%ld\nOK\r\n", block_CRC);
907
908                            if (strcmp(Answer, tmpString) != 0)
909                            {
910                                for (i = 0; i < Line; i++)
911                                {
912                                    SendComPort(IspEnvironment, sendbuf[i]);
913                                    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);
914                                }
915                            }
916                            else
917                                break;
918                        }
919
920                        if (repeat >= 3)
921                        {
922                            DebugPrintf(1, "Error on writing block_CRC (1)\n");
923                            return (ERROR_WRITE_CRC);
924                        }
925#else
926                        // printf("block_CRC = %ld\n", block_CRC);
927                        sprintf(tmpString, "%ld\r\n", block_CRC);
928                        SendComPort(IspEnvironment, tmpString);
929
930                        ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);
931
932                        sprintf(tmpString, "%ld\r\nOK\r\n", block_CRC);
933                        if (strcmp(Answer, tmpString) != 0)
934                        {
935                            DebugPrintf(1, "Error on writing block_CRC (1)\n");
936                            return (ERROR_WRITE_CRC);
937                        }
938#endif
939                        Line = 0;
940                        block_CRC = 0;
941                    }
942                }
943            }
944
945            if (Line != 0)
946            {
947#if !defined COMPILE_FOR_LPC21
948                for (repeat = 0; repeat < 3; repeat++)
949                {
950                    if (IspEnvironment->HalfDuplex == 0)
951                        sprintf(tmpString, "%ld\r\n", block_CRC);
952                    else
953                        sprintf(tmpString, "%ld\n", block_CRC);
954
955                    SendComPort(IspEnvironment, tmpString);
956
957                    ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);
958
959                    if (IspEnvironment->HalfDuplex == 0)
960                        sprintf(tmpString, "%ld\r\nOK\r\n", block_CRC);
961                    else
962                        sprintf(tmpString, "%ld\nOK\r\n", block_CRC);
963
964                    if (strcmp(Answer, tmpString) != 0)
965                    {
966                        for (i = 0; i < Line; i++)
967                        {
968                            SendComPort(IspEnvironment, sendbuf[i]);
969                            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);
970                        }
971                    }
972                    else
973                        break;
974                }
975
976                if (repeat >= 3)
977                {
978                    DebugPrintf(1, "Error on writing block_CRC (2)\n");
979                    return (ERROR_WRITE_CRC2);
980                }
981#else
982                sprintf(tmpString, "%ld\r\n", block_CRC);
983                SendComPort(IspEnvironment, tmpString);
984
985                ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);
986
987                sprintf(tmpString, "%ld\r\nOK\r\n", block_CRC);
988                if (strcmp(Answer, tmpString) != 0)
989                {
990                    DebugPrintf(1, "Error on writing block_CRC (2)\n");
991                    return (ERROR_WRITE_CRC2);
992                }
993#endif
994            }
995
996            if (IspEnvironment->BinaryOffset < LPC_RAMSTART)
997            {
998                // Prepare command must be repeated before every write
999                if (IspEnvironment->HalfDuplex == 0)
1000                    sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);
1001                else
1002                    sprintf(tmpString, "P %ld %ld\n", Sector, Sector);
1003
1004                if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
1005                {
1006                    DebugPrintf(1, "Wrong answer on Prepare-Command (2) (Sector %ld)\n", Sector);
1007                    return (WRONG_ANSWER_PREP2 + GetAndReportErrorNumber(Answer));
1008                }
1009
1010                // Round CopyLength up to one of the following values: 512, 1024,
1011                // 4096, 8192; but do not exceed the maximum copy size (usually
1012                // 8192, but chip-dependent)
1013                if (CopyLength < 512)
1014                {
1015                    CopyLength = 512;
1016                }
1017                else if (SectorLength < 1024)
1018                {
1019                    CopyLength = 1024;
1020                }
1021                else if (SectorLength < 4096)
1022                {
1023                    CopyLength = 4096;
1024                }
1025                else
1026                {
1027                    CopyLength = 8192;
1028                }
1029                if (CopyLength > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)
1030                {
1031                    CopyLength = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;
1032                }
1033
1034                if (IspEnvironment->HalfDuplex == 0)
1035                    sprintf(tmpString, "C %ld %ld %ld\r\n", SectorStart + SectorOffset, LPC_RAMBASE, CopyLength);
1036                else
1037                    sprintf(tmpString, "C %ld %ld %ld\n", SectorStart + SectorOffset, LPC_RAMBASE, CopyLength);
1038
1039                if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
1040                {
1041                    DebugPrintf(1, "Wrong answer on Copy-Command\n");
1042                    return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));
1043                }
1044
1045                if (IspEnvironment->Verify)
1046                {
1047
1048                    //Avoid compare first 64 bytes.
1049                    //Because first 64 bytes are re-mapped to flash boot sector,
1050                    //and the compare result may not be correct.
1051                    if (SectorStart + SectorOffset<64)
1052                    {
1053                        if (IspEnvironment->HalfDuplex == 0)
1054                            sprintf(tmpString, "M %ld %ld %ld\r\n", 64, LPC_RAMBASE + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));
1055                        else
1056                            sprintf(tmpString, "M %ld %ld %ld\n", 64, LPC_RAMBASE + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));
1057                    }
1058                    else
1059                    {
1060                        if (IspEnvironment->HalfDuplex == 0)
1061                            sprintf(tmpString, "M %ld %ld %ld\r\n", SectorStart + SectorOffset, LPC_RAMBASE, CopyLength);
1062                        else
1063                            sprintf(tmpString, "M %ld %ld %ld\n", SectorStart + SectorOffset, LPC_RAMBASE, CopyLength);
1064                    }
1065
1066                    if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
1067                    {
1068                        DebugPrintf(1, "Wrong answer on Compare-Command\n");
1069                        return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));
1070                    }
1071                }
1072            }
1073        }
1074
1075        DebugPrintf(2, "\n");
1076        fflush(stdout);
1077
1078        if ((SectorStart + SectorLength) >= IspEnvironment->BinaryLength && Sector!=0)
1079        {
1080            Sector = 0;
1081            SectorStart = 0;
1082        }
1083        else if (Sector == 0) {
1084            break;
1085        }
1086        else {
1087            SectorStart += LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];
1088            Sector++;
1089        }
1090    }
1091
1092    tDoneUpload = time(NULL);
1093    if (IspEnvironment->Verify)
1094        DebugPrintf(2, "Download Finished and Verified correct... taking %d seconds\n", tDoneUpload - tStartUpload);
1095    else
1096        DebugPrintf(2, "Download Finished... taking %d seconds\n", tDoneUpload - tStartUpload);
1097
1098    if (WaitForWatchDog)
1099    {
1100        DebugPrintf(2, "Wait for restart, in %d seconds from now\n", WatchDogSeconds - (tDoneUpload - tStartUpload));
1101    }
1102    else
1103    {
1104        DebugPrintf(2, "Now launching the brand new code\n");
1105        fflush(stdout);
1106
1107        if (IspEnvironment->HalfDuplex == 0)
1108            sprintf(tmpString, "G %ld A\r\n", IspEnvironment->StartAddress);
1109        else
1110            sprintf(tmpString, "G %ld A\n", IspEnvironment->StartAddress);
1111
1112        SendComPort(IspEnvironment, tmpString); //goto 0 : run this fresh new downloaded code code
1113        if (IspEnvironment->BinaryOffset < LPC_RAMSTART)
1114        { // Skip response on G command - show response on Terminal instead
1115            ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);
1116            /* the reply string is frequently terminated with a -1 (EOF) because the
1117            * connection gets broken; zero-terminate the string ourselves
1118            */
1119            while (realsize > 0 && ((signed char) Answer[(int)realsize - 1]) < 0)
1120                realsize--;
1121            Answer[(int)realsize] = '\0';
1122            /* Better to check only the first 9 chars instead of complete receive buffer,
1123            * because the answer can contain the output by the started programm
1124            */
1125            if (IspEnvironment->HalfDuplex == 0)
1126            {
1127                // This was not working with my LPC2214 most of the time - Herbert Demmel
1128                // was: cmdstr = "G 0 A\r\n0\r";
1129                cmdstr = "G 0 A\r\n0";
1130            }
1131            else
1132            {
1133                cmdstr = "G 0 A\n0\r";
1134            }
1135
1136            //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)
1137            if (realsize == 0 || strncmp((const char *)Answer, cmdstr, strlen(cmdstr)) != 0)
1138            {
1139                DebugPrintf(2, "Failed to run the new downloaded code: ");
1140                return (FAILED_RUN + GetAndReportErrorNumber(Answer));
1141            }
1142        }
1143
1144        fflush(stdout);
1145    }
1146    return (0);
1147}
1148#endif // LPC_SUPPORT
Note: See TracBrowser for help on using the browser.