]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - host/app/lpc21lisp/lpcprog.c
Add LPC21ISP to host
[fpga/lx-cpu1/lx-rocon.git] / host / app / lpc21lisp / lpcprog.c
1 /******************************************************************************\r
2 \r
3 Project:           Portable command line ISP for NXP LPC1000 / LPC2000 family\r
4                    and Analog Devices ADUC70xx\r
5 \r
6 Filename:          lpcprog.c\r
7 \r
8 Compiler:          Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
9                    GCC Cygwin, GCC Linux, GCC ARM ELF\r
10 \r
11 Author:            Martin Maurer (Martin.Maurer@clibb.de)\r
12 \r
13 Copyright:         (c) Martin Maurer 2003-2011, All rights reserved\r
14 Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
15 \r
16     This file is part of lpc21isp.\r
17 \r
18     lpc21isp is free software: you can redistribute it and/or modify\r
19     it under the terms of the GNU Lesser General Public License as published by\r
20     the Free Software Foundation, either version 3 of the License, or\r
21     any later version.\r
22 \r
23     lpc21isp is distributed in the hope that it will be useful,\r
24     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
25     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
26     GNU Lesser General Public License for more details.\r
27 \r
28     You should have received a copy of the GNU Lesser General Public License\r
29     and GNU General Public License along with lpc21isp.\r
30     If not, see <http://www.gnu.org/licenses/>.\r
31 */\r
32 \r
33 // This file is for the Actual Programming of the LPC Chips\r
34 \r
35 #if defined(_WIN32)\r
36 #include "malloc.h"\r
37 #if !defined __BORLANDC__\r
38 #include "StdAfx.h"\r
39 #endif\r
40 #endif // defined(_WIN32)\r
41 #include "lpc21isp.h"\r
42 \r
43 #ifdef LPC_SUPPORT\r
44 #include "lpcprog.h"\r
45 \r
46 static const unsigned int SectorTable_210x[] =\r
47 {\r
48     8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
49     8192, 8192, 8192, 8192, 8192, 8192, 8192\r
50 };\r
51 \r
52 static const unsigned int SectorTable_2103[] =\r
53 {\r
54     4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096\r
55 };\r
56 \r
57 static const unsigned int SectorTable_2109[] =\r
58 {\r
59     8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
60 };\r
61 \r
62 static const unsigned int SectorTable_211x[] =\r
63 {\r
64     8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
65     8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
66 };\r
67 \r
68 static const unsigned int SectorTable_212x[] =\r
69 {\r
70     8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
71     65536, 65536, 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
72 };\r
73 \r
74 // Used for devices with 500K (LPC2138 and LPC2148) and\r
75 // for devices with 504K (1 extra 4k block at the end)\r
76 static const unsigned int SectorTable_213x[] =\r
77 {\r
78      4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,\r
79     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,\r
80     32768, 32768, 32768, 32768, 32768, 32768,  4096,  4096,\r
81      4096,  4096,  4096,  4096\r
82 };\r
83 \r
84 // Used for LPC17xx devices\r
85 static const unsigned int SectorTable_17xx[] =\r
86 {\r
87      4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,\r
88      4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,\r
89     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,\r
90     32768, 32768, 32768, 32768, 32768, 32768\r
91 };\r
92 \r
93 // Used for LPC18xx devices\r
94 static const unsigned int SectorTable_18xx[] =\r
95 {\r
96      8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,\r
97     65536, 65536, 65536, 65536, 65536, 65536, 65536\r
98 };\r
99 \r
100 // Used for LPC43xx devices\r
101 static const unsigned int SectorTable_43xx[] =\r
102 {\r
103      8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,\r
104     65536, 65536, 65536, 65536, 65536, 65536, 65536\r
105 };\r
106 \r
107 // Used for LPC8xx devices\r
108 static const unsigned int SectorTable_8xx[] =\r
109 {\r
110      1024,  1024,  1024,  1024,  1024,  1024,  1024,  1024,\r
111      1024,  1024,  1024,  1024,  1024,  1024,  1024,  1024\r
112 };\r
113 \r
114 static int unsigned SectorTable_RAM[]  = { 65000 };\r
115 \r
116 static LPC_DEVICE_TYPE LPCtypes[] =\r
117 {\r
118    { 0, 0, 0, 0, 0, 0, 0, 0, 0, CHIP_VARIANT_NONE },  /* unknown */\r
119 \r
120    // id,        id2,  use id2, name of product, flash size, ram size, total number of sector, max copy size, sector table, chip variant\r
121 \r
122    { 0x00008100, 0x00000000, 0, "810M021FN8",     4,   1,  4,  256, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
123    { 0x00008110, 0x00000000, 0, "811M001FDH16",   8,   2,  8, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
124    { 0x00008120, 0x00000000, 0, "812M101FDH16",  16,   4, 16, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
125    { 0x00008121, 0x00000000, 0, "812M101FD20",   16,   4, 16, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
126    { 0x00008122, 0x00000000, 0, "812M101FDH20",  16,   4, 16, 1024, SectorTable_8xx,  CHIP_VARIANT_LPC8XX  },\r
127 \r
128    { 0x2500102B, 0x00000000, 0, "1102",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
129 \r
130    { 0x0A07102B, 0x00000000, 0, "1110.../002",    4,   1,  1, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
131    { 0x1A07102B, 0x00000000, 0, "1110.../002",    4,   1,  1, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
132    { 0x0A16D02B, 0x00000000, 0, "1111.../002",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
133    { 0x1A16D02B, 0x00000000, 0, "1111.../002",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
134    { 0x041E502B, 0x00000000, 0, "1111.../101",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
135    { 0x2516D02B, 0x00000000, 0, "1111.../102",    8,   2,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
136    { 0x0416502B, 0x00000000, 0, "1111.../201",    8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
137    { 0x2516902B, 0x00000000, 0, "1111.../202",    8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
138    { 0x042D502B, 0x00000000, 0, "1112.../101",   16,   2,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
139    { 0x2524D02B, 0x00000000, 0, "1112.../102",   16,   2,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
140    { 0x0A24902B, 0x00000000, 0, "1112.../102",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
141    { 0x1A24902B, 0x00000000, 0, "1112.../102",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
142    { 0x0425502B, 0x00000000, 0, "1112.../201",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
143    { 0x2524902B, 0x00000000, 0, "1112.../202",   16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
144    { 0x0434502B, 0x00000000, 0, "1113.../201",   24,   4,  6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
145    { 0x2532902B, 0x00000000, 0, "1113.../202",   24,   4,  6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
146    { 0x0434102B, 0x00000000, 0, "1113.../301",   24,   8,  6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
147    { 0x2532102B, 0x00000000, 0, "1113.../302",   24,   8,  6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
148    { 0x0A40902B, 0x00000000, 0, "1114.../102",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
149    { 0x1A40902B, 0x00000000, 0, "1114.../102",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
150    { 0x0444502B, 0x00000000, 0, "1114.../201",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
151    { 0x2540902B, 0x00000000, 0, "1114.../202",   32,   4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
152    { 0x0444102B, 0x00000000, 0, "1114.../301",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
153    { 0x2540102B, 0x00000000, 0, "1114.../302",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
154 \r
155    { 0x00040042, 0x00000000, 0, "1114.../203",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
156    { 0x00040040, 0x00000000, 0, "1114.../303",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
157    { 0x00040060, 0x00000000, 0, "1114.../323",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
158    { 0x00040070, 0x00000000, 0, "1114.../333",   32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
159    { 0x00050080, 0x00000000, 0, "1115.../303",   64,   8, 16, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
160 \r
161    { 0x1421102B, 0x00000000, 0, "11C12.../301",  16,   8,  4, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
162    { 0x1440102B, 0x00000000, 0, "11C14.../301",  32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
163    { 0x1431102B, 0x00000000, 0, "11C22.../301",  16,   8,  4, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
164    { 0x1430102B, 0x00000000, 0, "11C24.../301",  32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
165 \r
166    { 0x0364002B, 0x00000000, 0, "1224.../101",   32,   8,  4, 2048, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
167    { 0x0364202B, 0x00000000, 0, "1224.../121",   48,  12, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
168    { 0x0365002B, 0x00000000, 0, "1225.../301",   64,  16, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
169    { 0x0365202B, 0x00000000, 0, "1225.../321",   80,  20, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
170    { 0x0366002B, 0x00000000, 0, "1226",          96,  24, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
171    { 0x0367002B, 0x00000000, 0, "1227",         128,  32, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
172 \r
173    { 0x2C42502B, 0x00000000, 0, "1311",           8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
174    { 0x1816902B, 0x00000000, 0, "1311/01",        8,   4,  2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
175    { 0x2C40102B, 0x00000000, 0, "1313",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
176    { 0x1830102B, 0x00000000, 0, "1313/01",       32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
177    { 0x3D01402B, 0x00000000, 0, "1342",          16,   4,  4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
178    { 0x3D00002B, 0x00000000, 0, "1343",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
179 \r
180    { 0x25001118, 0x00000000, 0, "1751",          32,   8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
181    { 0x25001121, 0x00000000, 0, "1752",          64,  16, 16, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
182    { 0x25011722, 0x00000000, 0, "1754",         128,  32, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
183    { 0x25011723, 0x00000000, 0, "1756",         256,  32, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
184    { 0x25013F37, 0x00000000, 0, "1758",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
185    { 0x25113737, 0x00000000, 0, "1759",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
186    { 0x26011922, 0x00000000, 0, "1764",         128,  32, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
187    { 0x26013733, 0x00000000, 0, "1765",         256,  64, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
188    { 0x26013F33, 0x00000000, 0, "1766",         256,  64, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
189    { 0x26012837, 0x00000000, 0, "1767",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
190    { 0x26013F37, 0x00000000, 0, "1768",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
191    { 0x26113F37, 0x00000000, 0, "1769",         512,  64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
192 \r
193    { 0x27011132, 0x00000000, 0, "1774",         128,  40, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
194    { 0x27191F43, 0x00000000, 0, "1776",         256,  80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
195    { 0x27193747, 0x00000000, 0, "1777",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
196    { 0x27193F47, 0x00000000, 0, "1778",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
197    { 0x281D1743, 0x00000000, 0, "1785",         256,  80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
198    { 0x281D1F43, 0x00000000, 0, "1786",         256,  80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
199    { 0x281D3747, 0x00000000, 0, "1787",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
200    { 0x281D3F47, 0x00000000, 0, "1788",         512,  96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
201 \r
202    // LPC18xx\r
203    { 0xF00B1B3F, 0x00000000, 1, "1810",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
204    { 0xF00A9B3C, 0x00000000, 1, "1820",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
205    { 0xF0009A30, 0x00000000, 1, "1830",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
206    { 0xF001DA30, 0x00000044, 1, "1833",         512,  32, 11, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX },\r
207    { 0xF001DA30, 0x00000000, 1, "1837",        1024,  32, 15, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX },\r
208    { 0xF0009830, 0x00000000, 1, "1850",           0,  32,  0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
209    { 0xF001D830, 0x00000044, 1, "1853",         512,  32, 11, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // TODO - distinguish these parts (word 1)\r
210    { 0xF001D830, 0x00000000, 1, "1857",        1024,  32, 15, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // TODO - distinguish these parts (word 1)\r
211 \r
212    { 0x0004FF11, 0x00000000, 0, "2103",          32,   8,  8, 4096, SectorTable_2103, CHIP_VARIANT_LPC2XXX },\r
213    { 0xFFF0FF12, 0x00000000, 0, "2104",         128,  16, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
214    { 0xFFF0FF22, 0x00000000, 0, "2105",         128,  32, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
215    { 0xFFF0FF32, 0x00000000, 0, "2106",         128,  64, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
216    { 0x0201FF01, 0x00000000, 0, "2109",          64,   8,  8, 4096, SectorTable_2109, CHIP_VARIANT_LPC2XXX },\r
217    { 0x0101FF12, 0x00000000, 0, "2114",         128,  16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
218    { 0x0201FF12, 0x00000000, 0, "2119",         128,  16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
219    { 0x0101FF13, 0x00000000, 0, "2124",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
220    { 0x0201FF13, 0x00000000, 0, "2129",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
221    { 0x0002FF01, 0x00000000, 0, "2131",          32,   8,  8, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
222    { 0x0002FF11, 0x00000000, 0, "2132",          64,  16,  9, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
223    { 0x0002FF12, 0x00000000, 0, "2134",         128,  16, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
224    { 0x0002FF23, 0x00000000, 0, "2136",         256,  32, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
225    { 0x0002FF25, 0x00000000, 0, "2138",         512,  32, 27, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
226    { 0x0402FF01, 0x00000000, 0, "2141",          32,   8,  8, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
227    { 0x0402FF11, 0x00000000, 0, "2142",          64,  16,  9, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
228    { 0x0402FF12, 0x00000000, 0, "2144",         128,  16, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
229    { 0x0402FF23, 0x00000000, 0, "2146",         256,  40, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
230    { 0x0402FF25, 0x00000000, 0, "2148",         512,  40, 27, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
231    { 0x0301FF13, 0x00000000, 0, "2194",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
232    { 0x0301FF12, 0x00000000, 0, "2210",           0,  16,  0, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX }, /* table is a "don't care" */\r
233    { 0x0401FF12, 0x00000000, 0, "2212",         128,  16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
234    { 0x0601FF13, 0x00000000, 0, "2214",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
235    /*                           "2290"; same id as the LPC2210 */\r
236    { 0x0401FF13, 0x00000000, 0, "2292",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
237    { 0x0501FF13, 0x00000000, 0, "2294",         256,  16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
238    { 0x1600F701, 0x00000000, 0, "2361",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 4.1 -- 5 Sep 2012 */\r
239    { 0x1600FF22, 0x00000000, 0, "2362",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 4.1 -- 5 Sep 2012 */\r
240    { 0x0603FB02, 0x00000000, 0, "2364",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
241    { 0x1600F902, 0x00000000, 0, "2364",         128,  34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
242    { 0x1600E823, 0x00000000, 0, "2365",         256,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
243    { 0x0603FB23, 0x00000000, 0, "2366",         256,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
244    { 0x1600F923, 0x00000000, 0, "2366",         256,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
245    { 0x1600E825, 0x00000000, 0, "2367",         512,  58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
246    { 0x0603FB25, 0x00000000, 0, "2368",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
247    { 0x1600F925, 0x00000000, 0, "2368",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
248    { 0x1700E825, 0x00000000, 0, "2377",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
249    { 0x0703FF25, 0x00000000, 0, "2378",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
250    { 0x1600FD25, 0x00000000, 0, "2378",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 29 October 2007 */\r
251    { 0x1700FD25, 0x00000000, 0, "2378",         512,  58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
252    { 0x1700FF35, 0x00000000, 0, "2387",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 03 -- 25 August 2008 */\r
253    { 0x1800F935, 0x00000000, 0, "2387",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
254    { 0x1800FF35, 0x00000000, 0, "2388",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
255    { 0x1500FF35, 0x00000000, 0, "2458",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
256    { 0x1600FF30, 0x00000000, 0, "2460",           0,  98,  0, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
257    { 0x1600FF35, 0x00000000, 0, "2468",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
258    { 0x1701FF30, 0x00000000, 0, "2470",           0,  98,  0, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
259    { 0x1701FF35, 0x00000000, 0, "2478",         512,  98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
260 \r
261    { 0xA00A8B3F, 0x00000000, 1, "4310",           0, 168,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
262    { 0xA0008B3C, 0x00000000, 1, "4320",           0, 200,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
263    { 0xA0000A30, 0x00000000, 1, "4330",           0, 264,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
264    { 0xA001CA30, 0x00000044, 1, "4333",         512, 512, 11, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* info not yet available */\r
265    { 0xA001CA30, 0x00000000, 1, "4337",        1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* info not yet available */\r
266    { 0xA0000830, 0x00000000, 1, "4350",           0, 264,  0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
267    { 0xA001C830, 0x00000044, 1, "4353",         512, 512, 11, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
268    { 0xA001C830, 0x00000000, 1, "4357",        1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
269    { 0xA001C830, 0x0EF60000, 1, "4357",        1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }  /* info not yet available */\r
270 };\r
271 \r
272 /***************************** NXP Download *********************************/\r
273 /**  Download the file from the internal memory image to the NXP microcontroller.\r
274 *   This function is visible from outside if COMPILE_FOR_LPC21\r
275 */\r
276 \r
277 /***************************** FormatCommand ********************************/\r
278 /**  2013-06-28 Torsten Lang, Uwe Schneider GmbH\r
279 According to the various NXP user manuals the ISP bootloader commands should\r
280 be terminated with <CR><LF>, the echo and/or answer should have the same line\r
281 termination. So far for the theory...\r
282 In fact, the bootloader also accepts <LF> as line termination, but it may or\r
283 may not echo the linebreak character. Some bootloaders convert the character\r
284 into <CR><LF>, some leave the <LF> and append another one (<LF><LF> in the\r
285 answer). Furthermore, during uuencoded data transfer the bootloader may or\r
286 may not append an additional <LF> character at the end of the answer\r
287 (leading to a <CR><LF><LF> sequence).\r
288 A reliable way to handle these deviations from the UM is to strictly send the\r
289 commands according to the description in the UM and to re-format commands\r
290 and answers after a transfer.\r
291 FormatCommand works in a way that it drops any leading linefeeds which only\r
292 can be surplus <LF> characters from a previous answer. It then converts any\r
293 sequence of <CR> and <LF> into a single <LF> character.\r
294 FormatCommand can work in place, meaning that In==Out is allowed!\r
295 \param [in]  In  Pointer to input buffer.\r
296 \param [out] Out Pointer to output buffer.\r
297 */\r
298 \r
299 static void FormatCommand(const char *In, char *Out)\r
300 {\r
301   size_t i, j;\r
302   for (i = 0, j = 0; In[j] != '\0'; i++, j++)\r
303   {\r
304     if ((In[j] == '\r') || (In[j] == '\n'))\r
305     {\r
306       if (i > 0) // Ignore leading line breaks (they must be leftovers from a previous answer)\r
307       {\r
308         Out[i] = '\n';\r
309       }\r
310       else\r
311       {\r
312         i--;\r
313       }\r
314       while ((In[j+1] == '\r') || (In[j+1] == '\n'))\r
315       {\r
316         j++;\r
317       }\r
318     }\r
319     else\r
320     {\r
321       Out[i] = In[j];\r
322     }\r
323   }\r
324   Out[i] = '\0';\r
325 }\r
326 \r
327 static int SendAndVerify(ISP_ENVIRONMENT *IspEnvironment, const char *Command,\r
328                                  char *AnswerBuffer, int AnswerLength)\r
329 {\r
330     unsigned long realsize;\r
331     int cmdlen;\r
332     char *FormattedCommand;\r
333 \r
334     SendComPort(IspEnvironment, Command);\r
335     ReceiveComPort(IspEnvironment, AnswerBuffer, AnswerLength - 1, &realsize, 2, 5000);\r
336 \r
337     cmdlen = strlen(Command);\r
338     FormattedCommand = (char *)alloca(cmdlen+1);\r
339     FormatCommand(Command, FormattedCommand);\r
340     FormatCommand(AnswerBuffer, AnswerBuffer);\r
341     cmdlen = strlen(FormattedCommand);\r
342     return (strncmp(AnswerBuffer, FormattedCommand, cmdlen) == 0\r
343         && strcmp(AnswerBuffer + cmdlen, "0\n") == 0);\r
344 }\r
345 \r
346 \r
347 \r
348 /***************************** NxpOutputErrorMessage ***********************/\r
349 /**  Given an error number find and print the appropriate error message.\r
350 \param [in] ErrorNumber The number of the error.\r
351 */\r
352 #if defined COMPILE_FOR_LPC21\r
353 \r
354 #define NxpOutputErrorMessage(in)        // Cleanly remove this feature from the embedded version !!\r
355 \r
356 #else\r
357 \r
358 static void NxpOutputErrorMessage(unsigned char ErrorNumber)\r
359 {\r
360     switch (ErrorNumber)\r
361     {\r
362     case   0:\r
363         DebugPrintf(1, "CMD_SUCCESS\n");\r
364         break;\r
365 \r
366     case   1:\r
367         DebugPrintf(1, "INVALID_COMMAND\n");\r
368         break;\r
369 \r
370     case   2:\r
371         DebugPrintf(1, "SRC_ADDR_ERROR: Source address is not on word boundary.\n");\r
372         break;\r
373     case   3:\r
374         DebugPrintf(1, "DST_ADDR_ERROR: Destination address is not on a correct boundary.\n");\r
375         break;\r
376 \r
377     case   4:\r
378         DebugPrintf(1, "SRC_ADDR_NOT_MAPPED: Source address is not mapped in the memory map.\n"\r
379                        "                     Count value is taken into consideration where applicable.\n");\r
380         break;\r
381 \r
382     case   5:\r
383         DebugPrintf(1, "DST_ADDR_NOT_MAPPED: Destination address is not mapped in the memory map.\n"\r
384                        "                     Count value is taken into consideration where applicable.\n");\r
385         break;\r
386 \r
387     case   6:\r
388         DebugPrintf(1, "COUNT_ERROR: Byte count is not multiple of 4 or is not a permitted value.\n");\r
389         break;\r
390 \r
391     case   7:\r
392         DebugPrintf(1, "INVALID_SECTOR: Sector number is invalid or end sector number is\n"\r
393                        "                greater than start sector number.\n");\r
394         break;\r
395 \r
396     case   8:\r
397         DebugPrintf(1, "SECTOR_NOT_BLANK\n");\r
398         break;\r
399 \r
400     case   9:\r
401         DebugPrintf(1, "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION:\n"\r
402                        "Command to prepare sector for write operation was not executed.\n");\r
403         break;\r
404 \r
405     case  10:\r
406         DebugPrintf(1, "COMPARE_ERROR: Source and destination data not equal.\n");\r
407         break;\r
408 \r
409     case  11:\r
410         DebugPrintf(1, "BUSY: Flash programming hardware interface is busy.\n");\r
411         break;\r
412 \r
413     case  12:\r
414         DebugPrintf(1, "PARAM_ERROR: Insufficient number of parameters or invalid parameter.\n");\r
415         break;\r
416 \r
417     case  13:\r
418         DebugPrintf(1, "ADDR_ERROR: Address is not on word boundary.\n");\r
419         break;\r
420 \r
421     case  14:\r
422         DebugPrintf(1, "ADDR_NOT_MAPPED: Address is not mapped in the memory map.\n"\r
423                        "                 Count value is taken in to consideration where applicable.\n");\r
424         break;\r
425 \r
426     case  15:\r
427         DebugPrintf(1, "CMD_LOCKED\n");\r
428         break;\r
429 \r
430     case  16:\r
431         DebugPrintf(1, "INVALID_CODE: Unlock code is invalid.\n");\r
432         break;\r
433 \r
434     case  17:\r
435         DebugPrintf(1, "INVALID_BAUD_RATE: Invalid baud rate setting.\n");\r
436         break;\r
437 \r
438     case  18:\r
439         DebugPrintf(1, "INVALID_STOP_BIT: Invalid stop bit setting.\n");\r
440         break;\r
441 \r
442     case  19:\r
443         DebugPrintf( 1, "CODE READ PROTECTION ENABLED\n");\r
444         break;\r
445 \r
446     case 255:\r
447         break;\r
448 \r
449     default:\r
450         DebugPrintf(1, "unknown error %u\n", ErrorNumber);\r
451         break;\r
452     }\r
453 \r
454     //DebugPrintf(1, "error (%u), see  NxpOutputErrorMessage() in lpc21isp.c for help \n\r", ErrorNumber);\r
455 }\r
456 #endif // !defined COMPILE_FOR_LPC21\r
457 \r
458 /***************************** GetAndReportErrorNumber ***************************/\r
459 /**  Find error number in string.  This will normally be the string\r
460 returned from the microcontroller.\r
461 \param [in] Answer the buffer to search for the error number.\r
462 \return the error number found, if no linefeed found before the end of the\r
463 string an error value of 255 is returned. If a non-numeric value is found\r
464 then it is printed to stdout and an error value of 255 is returned.\r
465 */\r
466 static unsigned char GetAndReportErrorNumber(const char *Answer)\r
467 {\r
468     unsigned char Result = 0xFF;                            // Error !!!\r
469     unsigned int i = 0;\r
470 \r
471     while (1)\r
472     {\r
473         if (Answer[i] == 0x00)\r
474         {\r
475             break;\r
476         }\r
477 \r
478         if (Answer[i] == 0x0a)\r
479         {\r
480             i++;\r
481 \r
482             if (Answer[i] < '0' || Answer[i] > '9')\r
483             {\r
484                 DebugPrintf(1, "ErrorString: %s", &Answer[i]);\r
485                 break;\r
486             }\r
487 \r
488             Result = (unsigned char) (atoi(&Answer[i]));\r
489             break;\r
490         }\r
491 \r
492         i++;\r
493     }\r
494 \r
495     NxpOutputErrorMessage(Result);\r
496 \r
497     return Result;\r
498 }\r
499 \r
500 \r
501 int NxpDownload(ISP_ENVIRONMENT *IspEnvironment)\r
502 {\r
503     unsigned long realsize;\r
504     char Answer[128];\r
505     char ExpectedAnswer[128];\r
506     char temp[128];\r
507     /*const*/ char *strippedAnswer, *endPtr;\r
508     int  strippedsize;\r
509     int nQuestionMarks;\r
510     int found;\r
511     unsigned long Sector;\r
512     unsigned long SectorLength;\r
513     unsigned long SectorStart, SectorOffset, SectorChunk;\r
514     char tmpString[128];\r
515     char uuencode_table[64];\r
516     int Line;\r
517     unsigned long tmpStringPos;\r
518     unsigned long BlockOffset;\r
519     unsigned long Block;\r
520     unsigned long Pos;\r
521     unsigned long Id[2];\r
522     unsigned long CopyLength;\r
523     int c,k=0,i;\r
524     unsigned long ivt_CRC;          // CRC over interrupt vector table\r
525     unsigned long block_CRC;\r
526     time_t tStartUpload=0, tDoneUpload=0;\r
527     char tmp_string[64];\r
528     char * cmdstr;\r
529 \r
530 #if !defined COMPILE_FOR_LPC21\r
531 \r
532 #if defined __BORLANDC__\r
533 #define local_static static\r
534 #else\r
535 #define local_static\r
536 #endif\r
537 \r
538 //    char * cmdstr;\r
539     int repeat = 0;\r
540     // Puffer for data to resend after "RESEND\r\n" Target responce\r
541     local_static char sendbuf0[128];\r
542     local_static char sendbuf1[128];\r
543     local_static char sendbuf2[128];\r
544     local_static char sendbuf3[128];\r
545     local_static char sendbuf4[128];\r
546     local_static char sendbuf5[128];\r
547     local_static char sendbuf6[128];\r
548     local_static char sendbuf7[128];\r
549     local_static char sendbuf8[128];\r
550     local_static char sendbuf9[128];\r
551     local_static char sendbuf10[128];\r
552     local_static char sendbuf11[128];\r
553     local_static char sendbuf12[128];\r
554     local_static char sendbuf13[128];\r
555     local_static char sendbuf14[128];\r
556     local_static char sendbuf15[128];\r
557     local_static char sendbuf16[128];\r
558     local_static char sendbuf17[128];\r
559     local_static char sendbuf18[128];\r
560     local_static char sendbuf19[128];\r
561 \r
562     char * sendbuf[20] = {    sendbuf0,  sendbuf1,  sendbuf2,  sendbuf3,  sendbuf4,\r
563                               sendbuf5,  sendbuf6,  sendbuf7,  sendbuf8,  sendbuf9,\r
564                               sendbuf10, sendbuf11, sendbuf12, sendbuf13, sendbuf14,\r
565                               sendbuf15, sendbuf16, sendbuf17, sendbuf18, sendbuf19};\r
566 #endif\r
567 \r
568     DebugPrintf(2, "Synchronizing (ESC to abort)");\r
569 \r
570     PrepareKeyboardTtySettings();\r
571 \r
572 #if defined INTEGRATED_IN_WIN_APP\r
573     if (IspEnvironment->NoSync)\r
574     {\r
575         found = 1;\r
576     }\r
577     else\r
578 #endif\r
579     {\r
580         for (nQuestionMarks = found = 0; !found && nQuestionMarks < IspEnvironment->nQuestionMarks; nQuestionMarks++)\r
581         {\r
582 #if defined INTEGRATED_IN_WIN_APP\r
583             // allow calling application to abort when syncing takes too long\r
584 \r
585             if (!AppSyncing(nQuestionMarks))\r
586             {\r
587                 return (USER_ABORT_SYNC);\r
588             }\r
589 #else\r
590 #ifndef Exclude_kbhit\r
591             if (kbhit())\r
592             {\r
593                 if (getch() == 0x1b)\r
594                 {\r
595                     ResetKeyboardTtySettings();\r
596                     DebugPrintf(2, "\nUser aborted during synchronisation\n");\r
597                     return (USER_ABORT_SYNC);\r
598                 }\r
599             }\r
600 #endif\r
601 #endif\r
602 \r
603             DebugPrintf(2, ".");\r
604             SendComPort(IspEnvironment, "?");\r
605 \r
606             memset(Answer,0,sizeof(Answer));\r
607             ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,100);\r
608 \r
609             strippedAnswer = Answer;\r
610             strippedsize = realsize;\r
611             while ((strippedsize > 0) && ((*strippedAnswer == '?') || (*strippedAnswer == 0)))\r
612             {\r
613                 strippedAnswer++;\r
614                 strippedsize--;\r
615             }\r
616 \r
617             sprintf(tmp_string, "StrippedAnswer(Length=%d): ", strippedsize);\r
618             DumpString(3, strippedAnswer, strippedsize, tmp_string);\r
619 \r
620             tStartUpload = time(NULL);\r
621 \r
622             FormatCommand(strippedAnswer, strippedAnswer);\r
623             if (strcmp(strippedAnswer, "Synchronized\n") == 0)\r
624             {\r
625                 found = 1;\r
626             }\r
627 #if !defined COMPILE_FOR_LPC21\r
628             else\r
629             {\r
630                 ResetTarget(IspEnvironment, PROGRAM_MODE);\r
631             }\r
632 #endif\r
633         }\r
634     }\r
635 \r
636     ResetKeyboardTtySettings();\r
637 \r
638     if (!found)\r
639     {\r
640         DebugPrintf(1, " no answer on '?'\n");\r
641         return (NO_ANSWER_QM);\r
642     }\r
643 \r
644 #if defined INTEGRATED_IN_WIN_APP\r
645     AppSyncing(-1);                         // flag syncing done\r
646 #endif\r
647 \r
648     DebugPrintf(2, " OK\n");\r
649 \r
650     SendComPort(IspEnvironment, "Synchronized\r\n");\r
651 \r
652     ReceiveComPort(IspEnvironment, Answer, sizeof(Answer) - 1, &realsize, 2, 1000);\r
653 \r
654     FormatCommand(Answer, Answer);\r
655     if (strcmp(Answer, "Synchronized\nOK\n") != 0)\r
656     {\r
657         DebugPrintf(1, "No answer on 'Synchronized'\n");\r
658         return (NO_ANSWER_SYNC);\r
659     }\r
660 \r
661     DebugPrintf(3, "Synchronized 1\n");\r
662 \r
663     DebugPrintf(3, "Setting oscillator\n");\r
664 \r
665     sprintf(temp, "%s\r\n", IspEnvironment->StringOscillator);\r
666 \r
667     SendComPort(IspEnvironment, temp);\r
668 \r
669     ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 1000);\r
670 \r
671     sprintf(temp, "%s\nOK\n", IspEnvironment->StringOscillator);\r
672 \r
673     FormatCommand(Answer, Answer);\r
674     if (strcmp(Answer, temp) != 0)\r
675     {\r
676         DebugPrintf(1, "No answer on Oscillator-Command\n");\r
677         return (NO_ANSWER_OSC);\r
678     }\r
679 \r
680     DebugPrintf(3, "Unlock\n");\r
681 \r
682     cmdstr = "U 23130\r\n";\r
683 \r
684     if (!SendAndVerify(IspEnvironment, cmdstr, Answer, sizeof Answer))\r
685     {\r
686         DebugPrintf(1, "Unlock-Command:\n");\r
687         return (UNLOCK_ERROR + GetAndReportErrorNumber(Answer));\r
688     }\r
689 \r
690     DebugPrintf(2, "Read bootcode version: ");\r
691 \r
692     cmdstr = "K\r\n";\r
693 \r
694     SendComPort(IspEnvironment, cmdstr);\r
695 \r
696     ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 4,5000);\r
697 \r
698     FormatCommand(cmdstr, temp);\r
699     FormatCommand(Answer, Answer);\r
700     if (strncmp(Answer, temp, strlen(temp)) != 0)\r
701     {\r
702         DebugPrintf(1, "no answer on Read Boot Code Version\n");\r
703         return (NO_ANSWER_RBV);\r
704     }\r
705 \r
706     if (strncmp(Answer + strlen(temp), "0\n", 2) == 0)\r
707     {\r
708         strippedAnswer = Answer + strlen(temp) + 2;\r
709         /*\r
710         int maj, min, build;\r
711         if (sscanf(strippedAnswer, "%d %d %d", &build, &min, &maj) == 2) {\r
712         maj = min;\r
713         min = build;\r
714         build = 0;\r
715         } // if\r
716         DebugPrintf(2, "%d.%d.%d\n", maj, min, build);\r
717         */\r
718         DebugPrintf(2, strippedAnswer);\r
719     }\r
720     else\r
721     {\r
722         DebugPrintf(2, "unknown\n");\r
723     }\r
724 \r
725     DebugPrintf(2, "Read part ID: ");\r
726 \r
727     cmdstr = "J\r\n";\r
728 \r
729     SendComPort(IspEnvironment, cmdstr);\r
730 \r
731     ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 3, 5000);\r
732 \r
733     FormatCommand(cmdstr, temp);\r
734     FormatCommand(Answer, Answer);\r
735     if (strncmp(Answer, temp, strlen(temp)) != 0)\r
736     {\r
737         DebugPrintf(1, "no answer on Read Part Id\n");\r
738         return (NO_ANSWER_RPID);\r
739     }\r
740 \r
741     strippedAnswer = (strncmp(Answer, "J\n0\n", 4) == 0) ? Answer + 4 : Answer;\r
742 \r
743     Id[0] = strtoul(strippedAnswer, &endPtr, 10);\r
744     Id[1] = 0UL;\r
745     *endPtr = '\0'; /* delete \r\n */\r
746     for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && LPCtypes[i].id != Id[0]; i--)\r
747         /* nothing */;\r
748     IspEnvironment->DetectedDevice = i;\r
749     if (LPCtypes[IspEnvironment->DetectedDevice].EvalId2 != 0)\r
750     {\r
751         /* Read out the second configuration word and run the search again */\r
752         *endPtr = '\n';\r
753         endPtr++;\r
754         if ((endPtr[0] == '\0') || (endPtr[strlen(endPtr)-1] != '\n'))\r
755         {\r
756             /* No or incomplete word 2 */\r
757             ReceiveComPort(IspEnvironment, endPtr, sizeof(Answer)-(endPtr-Answer)-1, &realsize, 1, 100);\r
758         }\r
759 \r
760         FormatCommand(endPtr, endPtr);\r
761         if ((*endPtr == '\0') || (*endPtr == '\n'))\r
762         {\r
763             DebugPrintf(1, "incomplete answer on Read Part Id (second configuration word missing)\n");\r
764             return (NO_ANSWER_RPID);\r
765         }\r
766 \r
767         Id[1] = strtoul(endPtr, &endPtr, 10);\r
768         *endPtr = '\0'; /* delete \r\n */\r
769 \r
770         /* now search the table again */\r
771         for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && (LPCtypes[i].id != Id[0] || LPCtypes[i].id2 != Id[1]); i--)\r
772             /* nothing */;\r
773         IspEnvironment->DetectedDevice = i;\r
774     }\r
775     if (IspEnvironment->DetectedDevice == 0) {\r
776         DebugPrintf(2, "unknown");\r
777     }\r
778     else {\r
779         DebugPrintf(2, "LPC%s, %d kiB FLASH / %d kiB SRAM",\r
780             LPCtypes[IspEnvironment->DetectedDevice].Product,\r
781             LPCtypes[IspEnvironment->DetectedDevice].FlashSize,\r
782             LPCtypes[IspEnvironment->DetectedDevice].RAMSize);\r
783     }\r
784     if (LPCtypes[IspEnvironment->DetectedDevice].EvalId2 != 0)\r
785     {\r
786         DebugPrintf(2, " (0x%08lX / 0x%08lX)\n", Id[0], Id[1]);\r
787     }\r
788     else\r
789     {\r
790         DebugPrintf(2, " (0x%08lX)\n", Id[0]);\r
791     }\r
792 \r
793     if (!IspEnvironment->DetectOnly)\r
794     {\r
795         // Build up uuencode table\r
796         uuencode_table[0] = 0x60;           // 0x20 is translated to 0x60 !\r
797 \r
798         for (i = 1; i < 64; i++)\r
799         {\r
800             uuencode_table[i] = (char)(0x20 + i);\r
801         }\r
802 \r
803         if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
804         {\r
805             // Patch 0x14, otherwise it is not running and jumps to boot mode\r
806 \r
807             ivt_CRC = 0;\r
808 \r
809             // Clear the vector at 0x14 so it doesn't affect the checksum:\r
810             for (i = 0; i < 4; i++)\r
811             {\r
812                 IspEnvironment->BinaryContent[i + 0x14] = 0;\r
813             }\r
814 \r
815             // Calculate a native checksum of the little endian vector table:\r
816             for (i = 0; i < (4 * 8);) {\r
817                 ivt_CRC += IspEnvironment->BinaryContent[i++];\r
818                 ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;\r
819                 ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;\r
820                 ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;\r
821             }\r
822 \r
823             /* Negate the result and place in the vector at 0x14 as little endian\r
824             * again. The resulting vector table should checksum to 0. */\r
825             ivt_CRC = (unsigned long) (0 - ivt_CRC);\r
826             for (i = 0; i < 4; i++)\r
827             {\r
828                 IspEnvironment->BinaryContent[i + 0x14] = (unsigned char)(ivt_CRC >> (8 * i));\r
829             }\r
830 \r
831             DebugPrintf(3, "Position 0x14 patched: ivt_CRC = 0x%08lX\n", ivt_CRC);\r
832         }\r
833         else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
834                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
835                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
836                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
837                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
838                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
839         {\r
840             // Patch 0x1C, otherwise it is not running and jumps to boot mode\r
841 \r
842             ivt_CRC = 0;\r
843 \r
844             // Clear the vector at 0x1C so it doesn't affect the checksum:\r
845             for (i = 0; i < 4; i++)\r
846             {\r
847                 IspEnvironment->BinaryContent[i + 0x1C] = 0;\r
848             }\r
849 \r
850             // Calculate a native checksum of the little endian vector table:\r
851             for (i = 0; i < (4 * 8);) {\r
852                 ivt_CRC += IspEnvironment->BinaryContent[i++];\r
853                 ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;\r
854                 ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;\r
855                 ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;\r
856             }\r
857 \r
858             /* Negate the result and place in the vector at 0x1C as little endian\r
859             * again. The resulting vector table should checksum to 0. */\r
860             ivt_CRC = (unsigned long) (0 - ivt_CRC);\r
861             for (i = 0; i < 4; i++)\r
862             {\r
863                 IspEnvironment->BinaryContent[i + 0x1C] = (unsigned char)(ivt_CRC >> (8 * i));\r
864             }\r
865 \r
866             DebugPrintf(3, "Position 0x1C patched: ivt_CRC = 0x%08lX\n", ivt_CRC);\r
867         }\r
868         else\r
869         {\r
870           DebugPrintf(1, "Internal error: wrong chip variant %d (detected device %d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant, IspEnvironment->DetectedDevice);\r
871           exit(1);\r
872         }\r
873     }\r
874 \r
875 #if 0\r
876     DebugPrintf(2, "Read Unique ID:\n");\r
877 \r
878     cmdstr = "N\r\n";\r
879 \r
880     SendComPort(IspEnvironment, cmdstr);\r
881 \r
882     ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 5,5000);\r
883 \r
884     FormatCommand(cmdstr, temp);\r
885     FormatCommand(Answer, Answer);\r
886     if (strncmp(Answer, temp, strlen(temp)) != 0)\r
887     {\r
888         DebugPrintf(1, "no answer on Read Unique ID\n");\r
889         return (NO_ANSWER_RBV);\r
890     }\r
891 \r
892     if (strncmp(Answer + strlen(cmdstr), "0\n", 2) == 0)\r
893     {\r
894         strippedAnswer = Answer + strlen(temp) + 2;\r
895         DebugPrintf(2, strippedAnswer);\r
896     }\r
897     else\r
898     {\r
899         DebugPrintf(2, "unknown\n");\r
900     }\r
901 #endif // 0\r
902 \r
903     /* In case of a download to RAM, use full RAM for downloading\r
904     * set the flash parameters to full RAM also.\r
905     * This makes sure that all code is downloaded as one big sector\r
906     */\r
907 \r
908     if ( (IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment))\r
909        &&(IspEnvironment->BinaryOffset + IspEnvironment->BinaryLength <= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
910     {\r
911         LPCtypes[IspEnvironment->DetectedDevice].FlashSectors = 1;\r
912         LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize  = LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024 - (ReturnValueLpcRamBase(IspEnvironment) - ReturnValueLpcRamStart(IspEnvironment));\r
913         LPCtypes[IspEnvironment->DetectedDevice].SectorTable  = SectorTable_RAM;\r
914         SectorTable_RAM[0] = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
915     }\r
916     if (IspEnvironment->DetectOnly)\r
917         return (0);\r
918 \r
919     if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
920     {\r
921       // XON/XOFF must be switched off for LPC8XX\r
922       // otherwise problem during binary transmission of data to LPC8XX\r
923       DebugPrintf(3, "Switch off XON/XOFF !!!\n");\r
924       ControlXonXoffSerialPort(IspEnvironment, 0);\r
925     }\r
926 \r
927     // Start with sector 1 and go upward... Sector 0 containing the interrupt vectors\r
928     // will be loaded last, since it contains a checksum and device will re-enter\r
929     // bootloader mode as long as this checksum is invalid.\r
930     DebugPrintf(2, "Will start programming at Sector 1 if possible, and conclude with Sector 0 to ensure that checksum is written last.\n");\r
931     if (LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0] >= IspEnvironment->BinaryLength)\r
932     {\r
933         Sector = 0;\r
934         SectorStart = 0;\r
935     }\r
936     else\r
937     {\r
938         SectorStart = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0];\r
939         Sector = 1;\r
940     }\r
941 \r
942     if (IspEnvironment->WipeDevice == 1)\r
943     {\r
944         DebugPrintf(2, "Wiping Device. ");\r
945 \r
946         if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
947             LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
948         {\r
949             // TODO: Quick and dirty hack to address bank 0\r
950             sprintf(tmpString, "P %d %d 0\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
951         }\r
952         else\r
953         {\r
954             sprintf(tmpString, "P %d %d\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
955         }\r
956 \r
957         if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
958         {\r
959             DebugPrintf(1, "Wrong answer on Prepare-Command\n");\r
960             return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
961         }\r
962 \r
963         if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
964             LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
965         {\r
966             // TODO: Quick and dirty hack to address bank 0\r
967             sprintf(tmpString, "E %d %d 0\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
968         }\r
969         else\r
970         {\r
971             sprintf(tmpString, "E %d %d\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
972         }\r
973         if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
974         {\r
975             DebugPrintf(1, "Wrong answer on Erase-Command\n");\r
976             return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
977         }\r
978         DebugPrintf(2, "OK \n");\r
979 \r
980         if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
981             LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
982         {\r
983           DebugPrintf(2, "ATTENTION: Only bank A was wiped!!!\n");\r
984         }\r
985     }\r
986     else{\r
987         //no wiping requested: erasing sector 0 first\r
988         DebugPrintf(2, "Erasing sector 0 first, to invalidate checksum. ");\r
989 \r
990         if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
991             LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
992         {\r
993             // TODO: Quick and dirty hack to address bank 0\r
994             sprintf(tmpString, "P %d %d 0\r\n", 0, 0);\r
995         }\r
996         else\r
997         {\r
998             sprintf(tmpString, "P %d %d\r\n", 0, 0);\r
999         }\r
1000 \r
1001         if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1002         {\r
1003             DebugPrintf(1, "Wrong answer on Prepare-Command\n");\r
1004             return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
1005         }\r
1006 \r
1007         if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1008             LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1009         {\r
1010             // TODO: Quick and dirty hack to address bank 0\r
1011             sprintf(tmpString, "E %d %d 0\r\n", 0, 0);\r
1012         }\r
1013         else\r
1014         {\r
1015             sprintf(tmpString, "E %d %d\r\n", 0, 0);\r
1016         }\r
1017 \r
1018         if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1019         {\r
1020             DebugPrintf(1, "Wrong answer on Erase-Command\n");\r
1021             return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
1022         }\r
1023         DebugPrintf(2, "OK \n");\r
1024     }\r
1025     while (1)\r
1026     {\r
1027         if (Sector >= LPCtypes[IspEnvironment->DetectedDevice].FlashSectors)\r
1028         {\r
1029             DebugPrintf(1, "Program too large; running out of Flash sectors.\n");\r
1030             return (PROGRAM_TOO_LARGE);\r
1031         }\r
1032 \r
1033         DebugPrintf(2, "Sector %ld: ", Sector);\r
1034         fflush(stdout);\r
1035 \r
1036         if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))  // Skip Erase when running from RAM\r
1037            ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
1038         {\r
1039             if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1040                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1041             {\r
1042                 // TODO: Quick and dirty hack to address bank 0\r
1043                 sprintf(tmpString, "P %ld %ld 0\r\n", Sector, Sector);\r
1044             }\r
1045             else\r
1046             {\r
1047                 sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
1048             }\r
1049 \r
1050             if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1051             {\r
1052                 DebugPrintf(1, "Wrong answer on Prepare-Command (1) (Sector %ld)\n", Sector);\r
1053                 return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
1054             }\r
1055 \r
1056             DebugPrintf(2, ".");\r
1057             fflush(stdout);\r
1058             if (IspEnvironment->WipeDevice == 0 && (Sector!=0)) //Sector 0 already erased\r
1059             {\r
1060                 if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1061                     LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1062                 {\r
1063                     // TODO: Quick and dirty hack to address bank 0\r
1064                     sprintf(tmpString, "E %ld %ld 0\r\n", Sector, Sector);\r
1065                 }\r
1066                 else\r
1067                 {\r
1068                     sprintf(tmpString, "E %ld %ld\r\n", Sector, Sector);\r
1069                 }\r
1070 \r
1071                 if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1072                 {\r
1073                     DebugPrintf(1, "Wrong answer on Erase-Command (Sector %ld)\n", Sector);\r
1074                     return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
1075                 }\r
1076 \r
1077                 DebugPrintf(2, ".");\r
1078                 fflush(stdout);\r
1079             }\r
1080         }\r
1081 \r
1082         SectorLength = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];\r
1083         if (SectorLength > IspEnvironment->BinaryLength - SectorStart)\r
1084         {\r
1085             SectorLength = IspEnvironment->BinaryLength - SectorStart;\r
1086         }\r
1087 \r
1088         for (SectorOffset = 0; SectorOffset < SectorLength; SectorOffset += SectorChunk)\r
1089         {\r
1090             // Check if we are to write only 0xFFs - it would be just a waste of time..\r
1091             if (SectorOffset == 0) {\r
1092                 for (SectorOffset = 0; SectorOffset < SectorLength; ++SectorOffset)\r
1093                 {\r
1094                     if (IspEnvironment->BinaryContent[SectorStart + SectorOffset] != 0xFF)\r
1095                         break;\r
1096                 }\r
1097                 if (SectorOffset == SectorLength) // all data contents were 0xFFs\r
1098                 {\r
1099                     DebugPrintf(2, "Whole sector contents is 0xFFs, skipping programming.");\r
1100                     fflush(stdout);\r
1101                     break;\r
1102                 }\r
1103                 SectorOffset = 0; // re-set otherwise\r
1104             }\r
1105 \r
1106             if (SectorOffset > 0)\r
1107             {\r
1108                 // Add a visible marker between segments in a sector\r
1109                 DebugPrintf(2, "|");  /* means: partial segment copied */\r
1110                 fflush(stdout);\r
1111             }\r
1112 \r
1113             // If the Flash ROM sector size is bigger than the number of bytes\r
1114             // we can copy from RAM to Flash, we must "chop up" the sector and\r
1115             // copy these individually.\r
1116             // This is especially needed in the case where a Flash sector is\r
1117             // bigger than the amount of SRAM.\r
1118             SectorChunk = SectorLength - SectorOffset;\r
1119             if (SectorChunk > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)\r
1120             {\r
1121                 SectorChunk = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
1122             }\r
1123 \r
1124             // Write multiple of 45 * 4 Byte blocks to RAM, but copy maximum of on sector to Flash\r
1125             // In worst case we transfer up to 180 byte too much to RAM\r
1126             // but then we can always use full 45 byte blocks and length is multiple of 4\r
1127             CopyLength = SectorChunk;\r
1128 \r
1129             if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX ||\r
1130                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
1131                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
1132                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
1133                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
1134                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
1135             {\r
1136                 if ((CopyLength % (45 * 4)) != 0)\r
1137                 {\r
1138                     CopyLength += ((45 * 4) - (CopyLength % (45 * 4)));\r
1139                 }\r
1140             }\r
1141 \r
1142             sprintf(tmpString, "W %ld %ld\r\n", ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
1143 \r
1144             if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1145             {\r
1146                 DebugPrintf(1, "Wrong answer on Write-Command\n");\r
1147                 return (WRONG_ANSWER_WRIT + GetAndReportErrorNumber(Answer));\r
1148             }\r
1149 \r
1150             DebugPrintf(2, ".");\r
1151             fflush(stdout);\r
1152 \r
1153             if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX ||\r
1154                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
1155                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
1156                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
1157                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
1158                LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
1159             {\r
1160                 block_CRC = 0;\r
1161                 Line = 0;\r
1162 \r
1163                 // Transfer blocks of 45 * 4 bytes to RAM\r
1164                 for (Pos = SectorStart + SectorOffset; (Pos < SectorStart + SectorOffset + CopyLength) && (Pos < IspEnvironment->BinaryLength); Pos += (45 * 4))\r
1165                 {\r
1166                     for (Block = 0; Block < 4; Block++)  // Each block 45 bytes\r
1167                     {\r
1168                         DebugPrintf(2, ".");\r
1169                         fflush(stdout);\r
1170 \r
1171 #if defined INTEGRATED_IN_WIN_APP\r
1172                         // inform the calling application about having written another chuck of data\r
1173                         AppWritten(45);\r
1174 #endif\r
1175 \r
1176                         // Uuencode one 45 byte block\r
1177                         tmpStringPos = 0;\r
1178 \r
1179 #if !defined COMPILE_FOR_LPC21\r
1180                         sendbuf[Line][tmpStringPos++] = (char)(' ' + 45);    // Encode Length of block\r
1181 #else\r
1182                         tmpString[tmpStringPos++] = (char)(' ' + 45);        // Encode Length of block\r
1183 #endif\r
1184 \r
1185                         for (BlockOffset = 0; BlockOffset < 45; BlockOffset++)\r
1186                         {\r
1187                             if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))\r
1188                                ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
1189                             { // Flash: use full memory\r
1190                                 c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset];\r
1191                             }\r
1192                             else\r
1193                             { // RAM: Skip first 0x200 bytes, these are used by the download program in LPC21xx\r
1194                                 c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset + 0x200];\r
1195                             }\r
1196 \r
1197                             block_CRC += c;\r
1198 \r
1199                             k = (k << 8) + (c & 255);\r
1200 \r
1201                             if ((BlockOffset % 3) == 2)   // Collecting always 3 Bytes, then do processing in 4 Bytes\r
1202                             {\r
1203 #if !defined COMPILE_FOR_LPC21\r
1204                                 sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 18) & 63];\r
1205                                 sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 12) & 63];\r
1206                                 sendbuf[Line][tmpStringPos++] = uuencode_table[(k >>  6) & 63];\r
1207                                 sendbuf[Line][tmpStringPos++] = uuencode_table[ k        & 63];\r
1208 #else\r
1209                                 tmpString[tmpStringPos++] = uuencode_table[(k >> 18) & 63];\r
1210                                 tmpString[tmpStringPos++] = uuencode_table[(k >> 12) & 63];\r
1211                                 tmpString[tmpStringPos++] = uuencode_table[(k >>  6) & 63];\r
1212                                 tmpString[tmpStringPos++] = uuencode_table[ k        & 63];\r
1213 #endif\r
1214                             }\r
1215                         }\r
1216 \r
1217 \r
1218 #if !defined COMPILE_FOR_LPC21\r
1219                         sendbuf[Line][tmpStringPos++] = '\r';\r
1220                         sendbuf[Line][tmpStringPos++] = '\n';\r
1221                         sendbuf[Line][tmpStringPos++] = 0;\r
1222 \r
1223                         SendComPort(IspEnvironment, sendbuf[Line]);\r
1224                         // receive only for debug proposes\r
1225                         ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
1226                         FormatCommand(sendbuf[Line], tmpString);\r
1227                         FormatCommand(Answer, Answer);\r
1228                         if (strncmp(Answer, tmpString, strlen(tmpString)) != 0)\r
1229                         {\r
1230                             DebugPrintf(1, "Error on writing data (1)\n");\r
1231                             return (ERROR_WRITE_DATA);\r
1232                         }\r
1233 #else\r
1234                         tmpString[tmpStringPos++] = '\r';\r
1235                         tmpString[tmpStringPos++] = '\n';\r
1236                         tmpString[tmpStringPos++] = 0;\r
1237 \r
1238                         SendComPort(IspEnvironment, tmpString);\r
1239                         ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
1240                         FormatCommand(tmpString, tmpString);\r
1241                         FormatCommand(Answer, Answer);\r
1242                         if (strncmp(Answer, tmpString, tmpStringPos) != 0)\r
1243                         {\r
1244                             DebugPrintf(1, "Error on writing data (1)\n");\r
1245                             return (ERROR_WRITE_DATA);\r
1246                         }\r
1247 #endif\r
1248 \r
1249                         Line++;\r
1250 \r
1251                         DebugPrintf(3, "Line = %d\n", Line);\r
1252 \r
1253                         if (Line == 20)\r
1254                         {\r
1255 #if !defined COMPILE_FOR_LPC21\r
1256                             for (repeat = 0; repeat < 3; repeat++)\r
1257                             {\r
1258 \r
1259                                 // DebugPrintf(1, "block_CRC = %ld\n", block_CRC);\r
1260 \r
1261                                 sprintf(tmpString, "%ld\r\n", block_CRC);\r
1262 \r
1263                                 SendComPort(IspEnvironment, tmpString);\r
1264 \r
1265                                 ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);\r
1266 \r
1267                                 sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
1268 \r
1269                                 FormatCommand(tmpString, tmpString);\r
1270                                 FormatCommand(Answer, Answer);\r
1271                                 if (strcmp(Answer, tmpString) != 0)\r
1272                                 {\r
1273                                     for (i = 0; i < Line; i++)\r
1274                                     {\r
1275                                         SendComPort(IspEnvironment, sendbuf[i]);\r
1276                                         ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
1277                                     }\r
1278                                 }\r
1279                                 else\r
1280                                     break;\r
1281                             }\r
1282 \r
1283                             if (repeat >= 3)\r
1284                             {\r
1285                                 DebugPrintf(1, "Error on writing block_CRC (1)\n");\r
1286                                 return (ERROR_WRITE_CRC);\r
1287                             }\r
1288 #else\r
1289                             // DebugPrintf(1, "block_CRC = %ld\n", block_CRC);\r
1290                             sprintf(tmpString, "%ld\r\n", block_CRC);\r
1291                             SendComPort(IspEnvironment, tmpString);\r
1292 \r
1293                             ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
1294 \r
1295                             sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
1296                             FormatCommand(tmpString, tmpString);\r
1297                             FormatCommand(Answer, Answer);\r
1298                             if (strcmp(Answer, tmpString) != 0)\r
1299                             {\r
1300                                 DebugPrintf(1, "Error on writing block_CRC (2)\n");\r
1301                                 return (ERROR_WRITE_CRC);\r
1302                             }\r
1303 #endif\r
1304                             Line = 0;\r
1305                             block_CRC = 0;\r
1306                         }\r
1307                     }\r
1308                 }\r
1309 \r
1310                 if (Line != 0)\r
1311                 {\r
1312 #if !defined COMPILE_FOR_LPC21\r
1313                     for (repeat = 0; repeat < 3; repeat++)\r
1314                     {\r
1315                         sprintf(tmpString, "%ld\r\n", block_CRC);\r
1316 \r
1317                         SendComPort(IspEnvironment, tmpString);\r
1318 \r
1319                         ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
1320 \r
1321                         sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
1322 \r
1323                         FormatCommand(tmpString, tmpString);\r
1324                         FormatCommand(Answer, Answer);\r
1325                         if (strcmp(Answer, tmpString) != 0)\r
1326                         {\r
1327                             for (i = 0; i < Line; i++)\r
1328                             {\r
1329                                 SendComPort(IspEnvironment, sendbuf[i]);\r
1330                                 ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);\r
1331                             }\r
1332                         }\r
1333                         else\r
1334                             break;\r
1335                     }\r
1336 \r
1337                     if (repeat >= 3)\r
1338                     {\r
1339                         DebugPrintf(1, "Error on writing block_CRC (3)\n");\r
1340                         return (ERROR_WRITE_CRC2);\r
1341                     }\r
1342 #else\r
1343                     sprintf(tmpString, "%ld\r\n", block_CRC);\r
1344                     SendComPort(IspEnvironment, tmpString);\r
1345 \r
1346                     ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
1347 \r
1348                     sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
1349                     FormatCommand(tmpString, tmpString);\r
1350                     FormatCommand(Answer, Answer);\r
1351                     if (strcmp(Answer, tmpString) != 0)\r
1352                     {\r
1353                         DebugPrintf(1, "Error on writing block_CRC (4)\n");\r
1354                         return (ERROR_WRITE_CRC2);\r
1355                     }\r
1356 #endif\r
1357                 }\r
1358             }\r
1359             else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
1360             {\r
1361                 unsigned char BigAnswer[4096];\r
1362                 unsigned long CopyLengthPartialOffset = 0;\r
1363                 unsigned long CopyLengthPartialRemainingBytes;\r
1364 \r
1365                 while(CopyLengthPartialOffset < CopyLength)\r
1366                 {\r
1367                     CopyLengthPartialRemainingBytes = CopyLength - CopyLengthPartialOffset;\r
1368                     if(CopyLengthPartialRemainingBytes > 256)\r
1369                     {\r
1370                       // There seems to be an error in LPC812:\r
1371                       // When too much bytes are written at high speed,\r
1372                       // bytes get lost\r
1373                       // Workaround: Use smaller blocks\r
1374                       CopyLengthPartialRemainingBytes = 256;\r
1375                     }\r
1376 \r
1377                     SendComPortBlock(IspEnvironment, &IspEnvironment->BinaryContent[SectorStart + SectorOffset + CopyLengthPartialOffset], CopyLengthPartialRemainingBytes);\r
1378 \r
1379                     if (ReceiveComPortBlockComplete(IspEnvironment, &BigAnswer, CopyLengthPartialRemainingBytes, 10000) != 0)\r
1380                     {\r
1381                         return (ERROR_WRITE_DATA);\r
1382                     }\r
1383 \r
1384                     if(memcmp(&IspEnvironment->BinaryContent[SectorStart + SectorOffset + CopyLengthPartialOffset], BigAnswer, CopyLengthPartialRemainingBytes))\r
1385                     {\r
1386                         return (ERROR_WRITE_DATA);\r
1387                     }\r
1388 \r
1389                     CopyLengthPartialOffset += CopyLengthPartialRemainingBytes;\r
1390                 }\r
1391             }\r
1392 \r
1393             if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))\r
1394                ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
1395             {\r
1396                 // Prepare command must be repeated before every write\r
1397                 if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1398                     LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1399                 {\r
1400                     // TODO: Quick and dirty hack to address bank 0\r
1401                     sprintf(tmpString, "P %ld %ld 0\r\n", Sector, Sector);\r
1402                 }\r
1403                 else\r
1404                 {\r
1405                     sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
1406                 }\r
1407 \r
1408                 if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1409                 {\r
1410                     DebugPrintf(1, "Wrong answer on Prepare-Command (2) (Sector %ld)\n", Sector);\r
1411                     return (WRONG_ANSWER_PREP2 + GetAndReportErrorNumber(Answer));\r
1412                 }\r
1413 \r
1414                 // Round CopyLength up to one of the following values: 512, 1024,\r
1415                 // 4096, 8192; but do not exceed the maximum copy size (usually\r
1416                 // 8192, but chip-dependent)\r
1417                 if (CopyLength < 512)\r
1418                 {\r
1419                     CopyLength = 512;\r
1420                 }\r
1421                 else if (SectorLength < 1024)\r
1422                 {\r
1423                     CopyLength = 1024;\r
1424                 }\r
1425                 else if (SectorLength < 4096)\r
1426                 {\r
1427                     CopyLength = 4096;\r
1428                 }\r
1429                 else\r
1430                 {\r
1431                     CopyLength = 8192;\r
1432                 }\r
1433                 if (CopyLength > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)\r
1434                 {\r
1435                     CopyLength = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
1436                 }\r
1437 \r
1438                 sprintf(tmpString, "C %ld %ld %ld\r\n", IspEnvironment->BinaryOffset + SectorStart + SectorOffset, ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
1439 \r
1440                 if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1441                 {\r
1442                     DebugPrintf(1, "Wrong answer on Copy-Command\n");\r
1443                     return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));\r
1444                 }\r
1445 \r
1446                 if (IspEnvironment->Verify)\r
1447                 {\r
1448 \r
1449                     //Avoid compare first 64 bytes.\r
1450                     //Because first 64 bytes are re-mapped to flash boot sector,\r
1451                     //and the compare result may not be correct.\r
1452                     if (SectorStart + SectorOffset<64)\r
1453                     {\r
1454                         sprintf(tmpString, "M %d %ld %ld\r\n", 64, ReturnValueLpcRamBase(IspEnvironment) + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));\r
1455                     }\r
1456                     else\r
1457                     {\r
1458                         sprintf(tmpString, "M %ld %ld %ld\r\n", SectorStart + SectorOffset, ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
1459                     }\r
1460 \r
1461                     if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
1462                     {\r
1463                         DebugPrintf(1, "Wrong answer on Compare-Command\n");\r
1464                         return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));\r
1465                     }\r
1466                 }\r
1467             }\r
1468         }\r
1469 \r
1470         DebugPrintf(2, "\n");\r
1471         fflush(stdout);\r
1472 \r
1473         if ((SectorStart + SectorLength) >= IspEnvironment->BinaryLength && Sector!=0)\r
1474         {\r
1475             Sector = 0;\r
1476             SectorStart = 0;\r
1477         }\r
1478         else if (Sector == 0) {\r
1479             break;\r
1480         }\r
1481         else {\r
1482             SectorStart += LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];\r
1483             Sector++;\r
1484         }\r
1485     }\r
1486 \r
1487     tDoneUpload = time(NULL);\r
1488     if (IspEnvironment->Verify)\r
1489         DebugPrintf(2, "Download Finished and Verified correct... taking %d seconds\n", tDoneUpload - tStartUpload);\r
1490     else\r
1491         DebugPrintf(2, "Download Finished... taking %d seconds\n", tDoneUpload - tStartUpload);\r
1492 \r
1493     // For LPC18xx set boot bank to 0\r
1494     if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1495         LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1496     {\r
1497         if (!SendAndVerify(IspEnvironment, "S 0\r\n", Answer, sizeof Answer))\r
1498         {\r
1499             DebugPrintf(1, "Wrong answer on SetActiveBootFlashBank-Command\n");\r
1500             return (WRONG_ANSWER_BTBNK + GetAndReportErrorNumber(Answer));\r
1501         }\r
1502     }\r
1503 \r
1504     if(IspEnvironment->DoNotStart == 0)\r
1505     {\r
1506         DebugPrintf(2, "Now launching the brand new code\n");\r
1507         fflush(stdout);\r
1508 \r
1509         if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
1510         {\r
1511             sprintf(tmpString, "G %ld A\r\n", IspEnvironment->StartAddress);\r
1512         }\r
1513         else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1514                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
1515                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
1516                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
1517                 LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
1518         {\r
1519             sprintf(tmpString, "G %ld T\r\n", IspEnvironment->StartAddress & ~1);\r
1520         }\r
1521         else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
1522         {\r
1523             sprintf(tmpString, "G 0 T\r\n");\r
1524         }\r
1525         else\r
1526         {\r
1527             DebugPrintf(1, "Internal Error %s %d\n", __FILE__, __LINE__);\r
1528             exit(1);\r
1529         }\r
1530 \r
1531         SendComPort(IspEnvironment, tmpString); //goto 0 : run this fresh new downloaded code code\r
1532         if ( (IspEnvironment->BinaryOffset <  ReturnValueLpcRamStart(IspEnvironment))\r
1533            ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
1534         { // Skip response on G command - show response on Terminal instead\r
1535             ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);\r
1536             /* the reply string is frequently terminated with a -1 (EOF) because the\r
1537             * connection gets broken; zero-terminate the string ourselves\r
1538             */\r
1539             while (realsize > 0 && ((signed char) Answer[(int)realsize - 1]) < 0)\r
1540                 realsize--;\r
1541             Answer[(int)realsize] = '\0';\r
1542             /* Better to check only the first 9 chars instead of complete receive buffer,\r
1543             * because the answer can contain the output by the started programm\r
1544             */\r
1545             if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
1546             {\r
1547                 sprintf(ExpectedAnswer, "G %ld A\n0", IspEnvironment->StartAddress);\r
1548             }\r
1549             else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
1550                     LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
1551                     LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
1552                     LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
1553                     LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
1554             {\r
1555                 sprintf(ExpectedAnswer, "G %ld T\n0", IspEnvironment->StartAddress & ~1);\r
1556             }\r
1557             else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
1558             {\r
1559                 sprintf(ExpectedAnswer, "G 0 T\n0");\r
1560             }\r
1561             else\r
1562             {\r
1563                 DebugPrintf(1, "Internal Error %s %d\n", __FILE__, __LINE__);\r
1564                 exit(1);\r
1565             }\r
1566 \r
1567             FormatCommand(Answer, Answer);\r
1568             if (realsize == 0 || strncmp((const char *)Answer, /*cmdstr*/ExpectedAnswer, strlen(/*cmdstr*/ExpectedAnswer)) != 0)\r
1569             {\r
1570                 DebugPrintf(2, "Failed to run the new downloaded code: ");\r
1571                 return (FAILED_RUN + GetAndReportErrorNumber(Answer));\r
1572             }\r
1573         }\r
1574 \r
1575         fflush(stdout);\r
1576     }\r
1577     return (0);\r
1578 }\r
1579 #endif // LPC_SUPPORT\r
1580 \r
1581 \r
1582 unsigned long ReturnValueLpcRamStart(ISP_ENVIRONMENT *IspEnvironment)\r
1583 {\r
1584   if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
1585   {\r
1586     return LPC_RAMSTART_LPC43XX;\r
1587   }\r
1588   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
1589   {\r
1590     return LPC_RAMSTART_LPC2XXX;\r
1591   }\r
1592   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1593   {\r
1594     return LPC_RAMSTART_LPC18XX;\r
1595   }\r
1596   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX)\r
1597   {\r
1598     return LPC_RAMSTART_LPC17XX;\r
1599   }\r
1600   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX)\r
1601   {\r
1602     return LPC_RAMSTART_LPC13XX;\r
1603   }\r
1604   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
1605   {\r
1606     return LPC_RAMSTART_LPC11XX;\r
1607   }\r
1608   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
1609   {\r
1610     return LPC_RAMSTART_LPC8XX;\r
1611   }\r
1612   DebugPrintf(1, "Error in ReturnValueLpcRamStart (%d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant);\r
1613   exit(1);\r
1614 }\r
1615 \r
1616 \r
1617 unsigned long ReturnValueLpcRamBase(ISP_ENVIRONMENT *IspEnvironment)\r
1618 {\r
1619   if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
1620   {\r
1621     return LPC_RAMBASE_LPC43XX;\r
1622   }\r
1623   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
1624   {\r
1625     return LPC_RAMBASE_LPC2XXX;\r
1626   }\r
1627   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
1628   {\r
1629     return LPC_RAMBASE_LPC18XX;\r
1630   }\r
1631   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX)\r
1632   {\r
1633     return LPC_RAMBASE_LPC17XX;\r
1634   }\r
1635   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX)\r
1636   {\r
1637     return LPC_RAMBASE_LPC13XX;\r
1638   }\r
1639   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
1640   {\r
1641     return LPC_RAMBASE_LPC11XX;\r
1642   }\r
1643   else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
1644   {\r
1645     return LPC_RAMBASE_LPC8XX;\r
1646   }\r
1647   DebugPrintf(1, "Error in ReturnValueLpcRamBase (%d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant);\r
1648   exit(1);\r
1649 }\r