+/******************************************************************************\r
+\r
+Project: Portable command line ISP for NXP LPC1000 / LPC2000 family\r
+ and Analog Devices ADUC70xx\r
+\r
+Filename: lpcprog.c\r
+\r
+Compiler: Microsoft VC 6/7, Microsoft VS2008, Microsoft VS2010,\r
+ GCC Cygwin, GCC Linux, GCC ARM ELF\r
+\r
+Author: Martin Maurer (Martin.Maurer@clibb.de)\r
+\r
+Copyright: (c) Martin Maurer 2003-2011, All rights reserved\r
+Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com\r
+\r
+ This file is part of lpc21isp.\r
+\r
+ lpc21isp is free software: you can redistribute it and/or modify\r
+ it under the terms of the GNU Lesser General Public License as published by\r
+ the Free Software Foundation, either version 3 of the License, or\r
+ any later version.\r
+\r
+ lpc21isp is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU Lesser General Public License for more details.\r
+\r
+ You should have received a copy of the GNU Lesser General Public License\r
+ and GNU General Public License along with lpc21isp.\r
+ If not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+// This file is for the Actual Programming of the LPC Chips\r
+\r
+#if defined(_WIN32)\r
+#include "malloc.h"\r
+#if !defined __BORLANDC__\r
+#include "StdAfx.h"\r
+#endif\r
+#endif // defined(_WIN32)\r
+#include "lpc21isp.h"\r
+\r
+#ifdef LPC_SUPPORT\r
+#include "lpcprog.h"\r
+\r
+static const unsigned int SectorTable_210x[] =\r
+{\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
+};\r
+\r
+static const unsigned int SectorTable_2103[] =\r
+{\r
+ 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096\r
+};\r
+\r
+static const unsigned int SectorTable_2109[] =\r
+{\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
+};\r
+\r
+static const unsigned int SectorTable_211x[] =\r
+{\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+};\r
+\r
+static const unsigned int SectorTable_212x[] =\r
+{\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+ 65536, 65536, 8192, 8192, 8192, 8192, 8192, 8192, 8192\r
+};\r
+\r
+// Used for devices with 500K (LPC2138 and LPC2148) and\r
+// for devices with 504K (1 extra 4k block at the end)\r
+static const unsigned int SectorTable_213x[] =\r
+{\r
+ 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,\r
+ 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,\r
+ 32768, 32768, 32768, 32768, 32768, 32768, 4096, 4096,\r
+ 4096, 4096, 4096, 4096\r
+};\r
+\r
+// Used for LPC17xx devices\r
+static const unsigned int SectorTable_17xx[] =\r
+{\r
+ 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,\r
+ 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,\r
+ 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,\r
+ 32768, 32768, 32768, 32768, 32768, 32768\r
+};\r
+\r
+// Used for LPC18xx devices\r
+static const unsigned int SectorTable_18xx[] =\r
+{\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+ 65536, 65536, 65536, 65536, 65536, 65536, 65536\r
+};\r
+\r
+// Used for LPC43xx devices\r
+static const unsigned int SectorTable_43xx[] =\r
+{\r
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,\r
+ 65536, 65536, 65536, 65536, 65536, 65536, 65536\r
+};\r
+\r
+// Used for LPC8xx devices\r
+static const unsigned int SectorTable_8xx[] =\r
+{\r
+ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,\r
+ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024\r
+};\r
+\r
+static int unsigned SectorTable_RAM[] = { 65000 };\r
+\r
+static LPC_DEVICE_TYPE LPCtypes[] =\r
+{\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, CHIP_VARIANT_NONE }, /* unknown */\r
+\r
+ // id, id2, use id2, name of product, flash size, ram size, total number of sector, max copy size, sector table, chip variant\r
+\r
+ { 0x00008100, 0x00000000, 0, "810M021FN8", 4, 1, 4, 256, SectorTable_8xx, CHIP_VARIANT_LPC8XX },\r
+ { 0x00008110, 0x00000000, 0, "811M001FDH16", 8, 2, 8, 1024, SectorTable_8xx, CHIP_VARIANT_LPC8XX },\r
+ { 0x00008120, 0x00000000, 0, "812M101FDH16", 16, 4, 16, 1024, SectorTable_8xx, CHIP_VARIANT_LPC8XX },\r
+ { 0x00008121, 0x00000000, 0, "812M101FD20", 16, 4, 16, 1024, SectorTable_8xx, CHIP_VARIANT_LPC8XX },\r
+ { 0x00008122, 0x00000000, 0, "812M101FDH20", 16, 4, 16, 1024, SectorTable_8xx, CHIP_VARIANT_LPC8XX },\r
+\r
+ { 0x2500102B, 0x00000000, 0, "1102", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+ { 0x0A07102B, 0x00000000, 0, "1110.../002", 4, 1, 1, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1A07102B, 0x00000000, 0, "1110.../002", 4, 1, 1, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0A16D02B, 0x00000000, 0, "1111.../002", 8, 2, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1A16D02B, 0x00000000, 0, "1111.../002", 8, 2, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x041E502B, 0x00000000, 0, "1111.../101", 8, 2, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2516D02B, 0x00000000, 0, "1111.../102", 8, 2, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0416502B, 0x00000000, 0, "1111.../201", 8, 4, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2516902B, 0x00000000, 0, "1111.../202", 8, 4, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x042D502B, 0x00000000, 0, "1112.../101", 16, 2, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2524D02B, 0x00000000, 0, "1112.../102", 16, 2, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0A24902B, 0x00000000, 0, "1112.../102", 16, 4, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1A24902B, 0x00000000, 0, "1112.../102", 16, 4, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0425502B, 0x00000000, 0, "1112.../201", 16, 4, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2524902B, 0x00000000, 0, "1112.../202", 16, 4, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0434502B, 0x00000000, 0, "1113.../201", 24, 4, 6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2532902B, 0x00000000, 0, "1113.../202", 24, 4, 6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0434102B, 0x00000000, 0, "1113.../301", 24, 8, 6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2532102B, 0x00000000, 0, "1113.../302", 24, 8, 6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0A40902B, 0x00000000, 0, "1114.../102", 32, 4, 8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1A40902B, 0x00000000, 0, "1114.../102", 32, 4, 8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0444502B, 0x00000000, 0, "1114.../201", 32, 4, 8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2540902B, 0x00000000, 0, "1114.../202", 32, 4, 8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0444102B, 0x00000000, 0, "1114.../301", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x2540102B, 0x00000000, 0, "1114.../302", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+ { 0x00040042, 0x00000000, 0, "1114.../203", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x00040040, 0x00000000, 0, "1114.../303", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x00040060, 0x00000000, 0, "1114.../323", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x00040070, 0x00000000, 0, "1114.../333", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x00050080, 0x00000000, 0, "1115.../303", 64, 8, 16, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+ { 0x1421102B, 0x00000000, 0, "11C12.../301", 16, 8, 4, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1440102B, 0x00000000, 0, "11C14.../301", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1431102B, 0x00000000, 0, "11C22.../301", 16, 8, 4, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x1430102B, 0x00000000, 0, "11C24.../301", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+ { 0x0364002B, 0x00000000, 0, "1224.../101", 32, 8, 4, 2048, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0364202B, 0x00000000, 0, "1224.../121", 48, 12, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0365002B, 0x00000000, 0, "1225.../301", 64, 16, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0365202B, 0x00000000, 0, "1225.../321", 80, 20, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0366002B, 0x00000000, 0, "1226", 96, 24, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+ { 0x0367002B, 0x00000000, 0, "1227", 128, 32, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },\r
+\r
+ { 0x2C42502B, 0x00000000, 0, "1311", 8, 4, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+ { 0x1816902B, 0x00000000, 0, "1311/01", 8, 4, 2, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+ { 0x2C40102B, 0x00000000, 0, "1313", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+ { 0x1830102B, 0x00000000, 0, "1313/01", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+ { 0x3D01402B, 0x00000000, 0, "1342", 16, 4, 4, 1024, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+ { 0x3D00002B, 0x00000000, 0, "1343", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC13XX },\r
+\r
+ { 0x25001118, 0x00000000, 0, "1751", 32, 8, 8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x25001121, 0x00000000, 0, "1752", 64, 16, 16, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x25011722, 0x00000000, 0, "1754", 128, 32, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x25011723, 0x00000000, 0, "1756", 256, 32, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x25013F37, 0x00000000, 0, "1758", 512, 64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x25113737, 0x00000000, 0, "1759", 512, 64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x26011922, 0x00000000, 0, "1764", 128, 32, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x26013733, 0x00000000, 0, "1765", 256, 64, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x26013F33, 0x00000000, 0, "1766", 256, 64, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x26012837, 0x00000000, 0, "1767", 512, 64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x26013F37, 0x00000000, 0, "1768", 512, 64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x26113F37, 0x00000000, 0, "1769", 512, 64, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+\r
+ { 0x27011132, 0x00000000, 0, "1774", 128, 40, 18, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x27191F43, 0x00000000, 0, "1776", 256, 80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x27193747, 0x00000000, 0, "1777", 512, 96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x27193F47, 0x00000000, 0, "1778", 512, 96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x281D1743, 0x00000000, 0, "1785", 256, 80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x281D1F43, 0x00000000, 0, "1786", 256, 80, 22, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x281D3747, 0x00000000, 0, "1787", 512, 96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+ { 0x281D3F47, 0x00000000, 0, "1788", 512, 96, 30, 4096, SectorTable_17xx, CHIP_VARIANT_LPC17XX },\r
+\r
+ // LPC18xx\r
+ { 0xF00B1B3F, 0x00000000, 1, "1810", 0, 32, 0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+ { 0xF00A9B3C, 0x00000000, 1, "1820", 0, 32, 0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+ { 0xF0009A30, 0x00000000, 1, "1830", 0, 32, 0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+ { 0xF001DA30, 0x00000044, 1, "1833", 512, 32, 11, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX },\r
+ { 0xF001DA30, 0x00000000, 1, "1837", 1024, 32, 15, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX },\r
+ { 0xF0009830, 0x00000000, 1, "1850", 0, 32, 0, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // Flashless\r
+ { 0xF001D830, 0x00000044, 1, "1853", 512, 32, 11, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // TODO - distinguish these parts (word 1)\r
+ { 0xF001D830, 0x00000000, 1, "1857", 1024, 32, 15, 8192, SectorTable_18xx, CHIP_VARIANT_LPC18XX }, // TODO - distinguish these parts (word 1)\r
+\r
+ { 0x0004FF11, 0x00000000, 0, "2103", 32, 8, 8, 4096, SectorTable_2103, CHIP_VARIANT_LPC2XXX },\r
+ { 0xFFF0FF12, 0x00000000, 0, "2104", 128, 16, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
+ { 0xFFF0FF22, 0x00000000, 0, "2105", 128, 32, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
+ { 0xFFF0FF32, 0x00000000, 0, "2106", 128, 64, 15, 8192, SectorTable_210x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0201FF01, 0x00000000, 0, "2109", 64, 8, 8, 4096, SectorTable_2109, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0101FF12, 0x00000000, 0, "2114", 128, 16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0201FF12, 0x00000000, 0, "2119", 128, 16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0101FF13, 0x00000000, 0, "2124", 256, 16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0201FF13, 0x00000000, 0, "2129", 256, 16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0002FF01, 0x00000000, 0, "2131", 32, 8, 8, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0002FF11, 0x00000000, 0, "2132", 64, 16, 9, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0002FF12, 0x00000000, 0, "2134", 128, 16, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0002FF23, 0x00000000, 0, "2136", 256, 32, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0002FF25, 0x00000000, 0, "2138", 512, 32, 27, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0402FF01, 0x00000000, 0, "2141", 32, 8, 8, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0402FF11, 0x00000000, 0, "2142", 64, 16, 9, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0402FF12, 0x00000000, 0, "2144", 128, 16, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0402FF23, 0x00000000, 0, "2146", 256, 40, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0402FF25, 0x00000000, 0, "2148", 512, 40, 27, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0301FF13, 0x00000000, 0, "2194", 256, 16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0301FF12, 0x00000000, 0, "2210", 0, 16, 0, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX }, /* table is a "don't care" */\r
+ { 0x0401FF12, 0x00000000, 0, "2212", 128, 16, 15, 8192, SectorTable_211x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0601FF13, 0x00000000, 0, "2214", 256, 16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+ /* "2290"; same id as the LPC2210 */\r
+ { 0x0401FF13, 0x00000000, 0, "2292", 256, 16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0501FF13, 0x00000000, 0, "2294", 256, 16, 17, 8192, SectorTable_212x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1600F701, 0x00000000, 0, "2361", 128, 34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 4.1 -- 5 Sep 2012 */\r
+ { 0x1600FF22, 0x00000000, 0, "2362", 128, 34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 4.1 -- 5 Sep 2012 */\r
+ { 0x0603FB02, 0x00000000, 0, "2364", 128, 34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+ { 0x1600F902, 0x00000000, 0, "2364", 128, 34, 11, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1600E823, 0x00000000, 0, "2365", 256, 58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0603FB23, 0x00000000, 0, "2366", 256, 58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+ { 0x1600F923, 0x00000000, 0, "2366", 256, 58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1600E825, 0x00000000, 0, "2367", 512, 58, 15, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0603FB25, 0x00000000, 0, "2368", 512, 58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+ { 0x1600F925, 0x00000000, 0, "2368", 512, 58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1700E825, 0x00000000, 0, "2377", 512, 58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x0703FF25, 0x00000000, 0, "2378", 512, 58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 6 July 2007 */\r
+ { 0x1600FD25, 0x00000000, 0, "2378", 512, 58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 01 -- 29 October 2007 */\r
+ { 0x1700FD25, 0x00000000, 0, "2378", 512, 58, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1700FF35, 0x00000000, 0, "2387", 512, 98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX }, /* From UM10211 Rev. 03 -- 25 August 2008 */\r
+ { 0x1800F935, 0x00000000, 0, "2387", 512, 98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1800FF35, 0x00000000, 0, "2388", 512, 98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1500FF35, 0x00000000, 0, "2458", 512, 98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1600FF30, 0x00000000, 0, "2460", 0, 98, 0, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1600FF35, 0x00000000, 0, "2468", 512, 98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1701FF30, 0x00000000, 0, "2470", 0, 98, 0, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+ { 0x1701FF35, 0x00000000, 0, "2478", 512, 98, 28, 4096, SectorTable_213x, CHIP_VARIANT_LPC2XXX },\r
+\r
+ { 0xA00A8B3F, 0x00000000, 1, "4310", 0, 168, 0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+ { 0xA0008B3C, 0x00000000, 1, "4320", 0, 200, 0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+ { 0xA0000A30, 0x00000000, 1, "4330", 0, 264, 0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+ { 0xA001CA30, 0x00000044, 1, "4333", 512, 512, 11, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* info not yet available */\r
+ { 0xA001CA30, 0x00000000, 1, "4337", 1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* info not yet available */\r
+ { 0xA0000830, 0x00000000, 1, "4350", 0, 264, 0, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+ { 0xA001C830, 0x00000044, 1, "4353", 512, 512, 11, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+ { 0xA001C830, 0x00000000, 1, "4357", 1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX }, /* From UM10503 Rev. 1.4 -- 3 Sep 2012 */\r
+ { 0xA001C830, 0x0EF60000, 1, "4357", 1024, 512, 15, 4096, SectorTable_43xx, CHIP_VARIANT_LPC43XX } /* info not yet available */\r
+};\r
+\r
+/***************************** NXP Download *********************************/\r
+/** Download the file from the internal memory image to the NXP microcontroller.\r
+* This function is visible from outside if COMPILE_FOR_LPC21\r
+*/\r
+\r
+/***************************** FormatCommand ********************************/\r
+/** 2013-06-28 Torsten Lang, Uwe Schneider GmbH\r
+According to the various NXP user manuals the ISP bootloader commands should\r
+be terminated with <CR><LF>, the echo and/or answer should have the same line\r
+termination. So far for the theory...\r
+In fact, the bootloader also accepts <LF> as line termination, but it may or\r
+may not echo the linebreak character. Some bootloaders convert the character\r
+into <CR><LF>, some leave the <LF> and append another one (<LF><LF> in the\r
+answer). Furthermore, during uuencoded data transfer the bootloader may or\r
+may not append an additional <LF> character at the end of the answer\r
+(leading to a <CR><LF><LF> sequence).\r
+A reliable way to handle these deviations from the UM is to strictly send the\r
+commands according to the description in the UM and to re-format commands\r
+and answers after a transfer.\r
+FormatCommand works in a way that it drops any leading linefeeds which only\r
+can be surplus <LF> characters from a previous answer. It then converts any\r
+sequence of <CR> and <LF> into a single <LF> character.\r
+FormatCommand can work in place, meaning that In==Out is allowed!\r
+\param [in] In Pointer to input buffer.\r
+\param [out] Out Pointer to output buffer.\r
+*/\r
+\r
+static void FormatCommand(const char *In, char *Out)\r
+{\r
+ size_t i, j;\r
+ for (i = 0, j = 0; In[j] != '\0'; i++, j++)\r
+ {\r
+ if ((In[j] == '\r') || (In[j] == '\n'))\r
+ {\r
+ if (i > 0) // Ignore leading line breaks (they must be leftovers from a previous answer)\r
+ {\r
+ Out[i] = '\n';\r
+ }\r
+ else\r
+ {\r
+ i--;\r
+ }\r
+ while ((In[j+1] == '\r') || (In[j+1] == '\n'))\r
+ {\r
+ j++;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Out[i] = In[j];\r
+ }\r
+ }\r
+ Out[i] = '\0';\r
+}\r
+\r
+static int SendAndVerify(ISP_ENVIRONMENT *IspEnvironment, const char *Command,\r
+ char *AnswerBuffer, int AnswerLength)\r
+{\r
+ unsigned long realsize;\r
+ int cmdlen;\r
+ char *FormattedCommand;\r
+\r
+ SendComPort(IspEnvironment, Command);\r
+ ReceiveComPort(IspEnvironment, AnswerBuffer, AnswerLength - 1, &realsize, 2, 5000);\r
+\r
+ cmdlen = strlen(Command);\r
+ FormattedCommand = (char *)alloca(cmdlen+1);\r
+ FormatCommand(Command, FormattedCommand);\r
+ FormatCommand(AnswerBuffer, AnswerBuffer);\r
+ cmdlen = strlen(FormattedCommand);\r
+ return (strncmp(AnswerBuffer, FormattedCommand, cmdlen) == 0\r
+ && strcmp(AnswerBuffer + cmdlen, "0\n") == 0);\r
+}\r
+\r
+\r
+\r
+/***************************** NxpOutputErrorMessage ***********************/\r
+/** Given an error number find and print the appropriate error message.\r
+\param [in] ErrorNumber The number of the error.\r
+*/\r
+#if defined COMPILE_FOR_LPC21\r
+\r
+#define NxpOutputErrorMessage(in) // Cleanly remove this feature from the embedded version !!\r
+\r
+#else\r
+\r
+static void NxpOutputErrorMessage(unsigned char ErrorNumber)\r
+{\r
+ switch (ErrorNumber)\r
+ {\r
+ case 0:\r
+ DebugPrintf(1, "CMD_SUCCESS\n");\r
+ break;\r
+\r
+ case 1:\r
+ DebugPrintf(1, "INVALID_COMMAND\n");\r
+ break;\r
+\r
+ case 2:\r
+ DebugPrintf(1, "SRC_ADDR_ERROR: Source address is not on word boundary.\n");\r
+ break;\r
+ case 3:\r
+ DebugPrintf(1, "DST_ADDR_ERROR: Destination address is not on a correct boundary.\n");\r
+ break;\r
+\r
+ case 4:\r
+ DebugPrintf(1, "SRC_ADDR_NOT_MAPPED: Source address is not mapped in the memory map.\n"\r
+ " Count value is taken into consideration where applicable.\n");\r
+ break;\r
+\r
+ case 5:\r
+ DebugPrintf(1, "DST_ADDR_NOT_MAPPED: Destination address is not mapped in the memory map.\n"\r
+ " Count value is taken into consideration where applicable.\n");\r
+ break;\r
+\r
+ case 6:\r
+ DebugPrintf(1, "COUNT_ERROR: Byte count is not multiple of 4 or is not a permitted value.\n");\r
+ break;\r
+\r
+ case 7:\r
+ DebugPrintf(1, "INVALID_SECTOR: Sector number is invalid or end sector number is\n"\r
+ " greater than start sector number.\n");\r
+ break;\r
+\r
+ case 8:\r
+ DebugPrintf(1, "SECTOR_NOT_BLANK\n");\r
+ break;\r
+\r
+ case 9:\r
+ DebugPrintf(1, "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION:\n"\r
+ "Command to prepare sector for write operation was not executed.\n");\r
+ break;\r
+\r
+ case 10:\r
+ DebugPrintf(1, "COMPARE_ERROR: Source and destination data not equal.\n");\r
+ break;\r
+\r
+ case 11:\r
+ DebugPrintf(1, "BUSY: Flash programming hardware interface is busy.\n");\r
+ break;\r
+\r
+ case 12:\r
+ DebugPrintf(1, "PARAM_ERROR: Insufficient number of parameters or invalid parameter.\n");\r
+ break;\r
+\r
+ case 13:\r
+ DebugPrintf(1, "ADDR_ERROR: Address is not on word boundary.\n");\r
+ break;\r
+\r
+ case 14:\r
+ DebugPrintf(1, "ADDR_NOT_MAPPED: Address is not mapped in the memory map.\n"\r
+ " Count value is taken in to consideration where applicable.\n");\r
+ break;\r
+\r
+ case 15:\r
+ DebugPrintf(1, "CMD_LOCKED\n");\r
+ break;\r
+\r
+ case 16:\r
+ DebugPrintf(1, "INVALID_CODE: Unlock code is invalid.\n");\r
+ break;\r
+\r
+ case 17:\r
+ DebugPrintf(1, "INVALID_BAUD_RATE: Invalid baud rate setting.\n");\r
+ break;\r
+\r
+ case 18:\r
+ DebugPrintf(1, "INVALID_STOP_BIT: Invalid stop bit setting.\n");\r
+ break;\r
+\r
+ case 19:\r
+ DebugPrintf( 1, "CODE READ PROTECTION ENABLED\n");\r
+ break;\r
+\r
+ case 255:\r
+ break;\r
+\r
+ default:\r
+ DebugPrintf(1, "unknown error %u\n", ErrorNumber);\r
+ break;\r
+ }\r
+\r
+ //DebugPrintf(1, "error (%u), see NxpOutputErrorMessage() in lpc21isp.c for help \n\r", ErrorNumber);\r
+}\r
+#endif // !defined COMPILE_FOR_LPC21\r
+\r
+/***************************** GetAndReportErrorNumber ***************************/\r
+/** Find error number in string. This will normally be the string\r
+returned from the microcontroller.\r
+\param [in] Answer the buffer to search for the error number.\r
+\return the error number found, if no linefeed found before the end of the\r
+string an error value of 255 is returned. If a non-numeric value is found\r
+then it is printed to stdout and an error value of 255 is returned.\r
+*/\r
+static unsigned char GetAndReportErrorNumber(const char *Answer)\r
+{\r
+ unsigned char Result = 0xFF; // Error !!!\r
+ unsigned int i = 0;\r
+\r
+ while (1)\r
+ {\r
+ if (Answer[i] == 0x00)\r
+ {\r
+ break;\r
+ }\r
+\r
+ if (Answer[i] == 0x0a)\r
+ {\r
+ i++;\r
+\r
+ if (Answer[i] < '0' || Answer[i] > '9')\r
+ {\r
+ DebugPrintf(1, "ErrorString: %s", &Answer[i]);\r
+ break;\r
+ }\r
+\r
+ Result = (unsigned char) (atoi(&Answer[i]));\r
+ break;\r
+ }\r
+\r
+ i++;\r
+ }\r
+\r
+ NxpOutputErrorMessage(Result);\r
+\r
+ return Result;\r
+}\r
+\r
+\r
+int NxpDownload(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+ unsigned long realsize;\r
+ char Answer[128];\r
+ char ExpectedAnswer[128];\r
+ char temp[128];\r
+ /*const*/ char *strippedAnswer, *endPtr;\r
+ int strippedsize;\r
+ int nQuestionMarks;\r
+ int found;\r
+ unsigned long Sector;\r
+ unsigned long SectorLength;\r
+ unsigned long SectorStart, SectorOffset, SectorChunk;\r
+ char tmpString[128];\r
+ char uuencode_table[64];\r
+ int Line;\r
+ unsigned long tmpStringPos;\r
+ unsigned long BlockOffset;\r
+ unsigned long Block;\r
+ unsigned long Pos;\r
+ unsigned long Id[2];\r
+ unsigned long CopyLength;\r
+ int c,k=0,i;\r
+ unsigned long ivt_CRC; // CRC over interrupt vector table\r
+ unsigned long block_CRC;\r
+ time_t tStartUpload=0, tDoneUpload=0;\r
+ char tmp_string[64];\r
+ char * cmdstr;\r
+\r
+#if !defined COMPILE_FOR_LPC21\r
+\r
+#if defined __BORLANDC__\r
+#define local_static static\r
+#else\r
+#define local_static\r
+#endif\r
+\r
+// char * cmdstr;\r
+ int repeat = 0;\r
+ // Puffer for data to resend after "RESEND\r\n" Target responce\r
+ local_static char sendbuf0[128];\r
+ local_static char sendbuf1[128];\r
+ local_static char sendbuf2[128];\r
+ local_static char sendbuf3[128];\r
+ local_static char sendbuf4[128];\r
+ local_static char sendbuf5[128];\r
+ local_static char sendbuf6[128];\r
+ local_static char sendbuf7[128];\r
+ local_static char sendbuf8[128];\r
+ local_static char sendbuf9[128];\r
+ local_static char sendbuf10[128];\r
+ local_static char sendbuf11[128];\r
+ local_static char sendbuf12[128];\r
+ local_static char sendbuf13[128];\r
+ local_static char sendbuf14[128];\r
+ local_static char sendbuf15[128];\r
+ local_static char sendbuf16[128];\r
+ local_static char sendbuf17[128];\r
+ local_static char sendbuf18[128];\r
+ local_static char sendbuf19[128];\r
+\r
+ char * sendbuf[20] = { sendbuf0, sendbuf1, sendbuf2, sendbuf3, sendbuf4,\r
+ sendbuf5, sendbuf6, sendbuf7, sendbuf8, sendbuf9,\r
+ sendbuf10, sendbuf11, sendbuf12, sendbuf13, sendbuf14,\r
+ sendbuf15, sendbuf16, sendbuf17, sendbuf18, sendbuf19};\r
+#endif\r
+\r
+ DebugPrintf(2, "Synchronizing (ESC to abort)");\r
+\r
+ PrepareKeyboardTtySettings();\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+ if (IspEnvironment->NoSync)\r
+ {\r
+ found = 1;\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ for (nQuestionMarks = found = 0; !found && nQuestionMarks < IspEnvironment->nQuestionMarks; nQuestionMarks++)\r
+ {\r
+#if defined INTEGRATED_IN_WIN_APP\r
+ // allow calling application to abort when syncing takes too long\r
+\r
+ if (!AppSyncing(nQuestionMarks))\r
+ {\r
+ return (USER_ABORT_SYNC);\r
+ }\r
+#else\r
+#ifndef Exclude_kbhit\r
+ if (kbhit())\r
+ {\r
+ if (getch() == 0x1b)\r
+ {\r
+ ResetKeyboardTtySettings();\r
+ DebugPrintf(2, "\nUser aborted during synchronisation\n");\r
+ return (USER_ABORT_SYNC);\r
+ }\r
+ }\r
+#endif\r
+#endif\r
+\r
+ DebugPrintf(2, ".");\r
+ SendComPort(IspEnvironment, "?");\r
+\r
+ memset(Answer,0,sizeof(Answer));\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,100);\r
+\r
+ strippedAnswer = Answer;\r
+ strippedsize = realsize;\r
+ while ((strippedsize > 0) && ((*strippedAnswer == '?') || (*strippedAnswer == 0)))\r
+ {\r
+ strippedAnswer++;\r
+ strippedsize--;\r
+ }\r
+\r
+ sprintf(tmp_string, "StrippedAnswer(Length=%d): ", strippedsize);\r
+ DumpString(3, strippedAnswer, strippedsize, tmp_string);\r
+\r
+ tStartUpload = time(NULL);\r
+\r
+ FormatCommand(strippedAnswer, strippedAnswer);\r
+ if (strcmp(strippedAnswer, "Synchronized\n") == 0)\r
+ {\r
+ found = 1;\r
+ }\r
+#if !defined COMPILE_FOR_LPC21\r
+ else\r
+ {\r
+ ResetTarget(IspEnvironment, PROGRAM_MODE);\r
+ }\r
+#endif\r
+ }\r
+ }\r
+\r
+ ResetKeyboardTtySettings();\r
+\r
+ if (!found)\r
+ {\r
+ DebugPrintf(1, " no answer on '?'\n");\r
+ return (NO_ANSWER_QM);\r
+ }\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+ AppSyncing(-1); // flag syncing done\r
+#endif\r
+\r
+ DebugPrintf(2, " OK\n");\r
+\r
+ SendComPort(IspEnvironment, "Synchronized\r\n");\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer) - 1, &realsize, 2, 1000);\r
+\r
+ FormatCommand(Answer, Answer);\r
+ if (strcmp(Answer, "Synchronized\nOK\n") != 0)\r
+ {\r
+ DebugPrintf(1, "No answer on 'Synchronized'\n");\r
+ return (NO_ANSWER_SYNC);\r
+ }\r
+\r
+ DebugPrintf(3, "Synchronized 1\n");\r
+\r
+ DebugPrintf(3, "Setting oscillator\n");\r
+\r
+ sprintf(temp, "%s\r\n", IspEnvironment->StringOscillator);\r
+\r
+ SendComPort(IspEnvironment, temp);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 1000);\r
+\r
+ sprintf(temp, "%s\nOK\n", IspEnvironment->StringOscillator);\r
+\r
+ FormatCommand(Answer, Answer);\r
+ if (strcmp(Answer, temp) != 0)\r
+ {\r
+ DebugPrintf(1, "No answer on Oscillator-Command\n");\r
+ return (NO_ANSWER_OSC);\r
+ }\r
+\r
+ DebugPrintf(3, "Unlock\n");\r
+\r
+ cmdstr = "U 23130\r\n";\r
+\r
+ if (!SendAndVerify(IspEnvironment, cmdstr, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Unlock-Command:\n");\r
+ return (UNLOCK_ERROR + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ DebugPrintf(2, "Read bootcode version: ");\r
+\r
+ cmdstr = "K\r\n";\r
+\r
+ SendComPort(IspEnvironment, cmdstr);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 4,5000);\r
+\r
+ FormatCommand(cmdstr, temp);\r
+ FormatCommand(Answer, Answer);\r
+ if (strncmp(Answer, temp, strlen(temp)) != 0)\r
+ {\r
+ DebugPrintf(1, "no answer on Read Boot Code Version\n");\r
+ return (NO_ANSWER_RBV);\r
+ }\r
+\r
+ if (strncmp(Answer + strlen(temp), "0\n", 2) == 0)\r
+ {\r
+ strippedAnswer = Answer + strlen(temp) + 2;\r
+ /*\r
+ int maj, min, build;\r
+ if (sscanf(strippedAnswer, "%d %d %d", &build, &min, &maj) == 2) {\r
+ maj = min;\r
+ min = build;\r
+ build = 0;\r
+ } // if\r
+ DebugPrintf(2, "%d.%d.%d\n", maj, min, build);\r
+ */\r
+ DebugPrintf(2, strippedAnswer);\r
+ }\r
+ else\r
+ {\r
+ DebugPrintf(2, "unknown\n");\r
+ }\r
+\r
+ DebugPrintf(2, "Read part ID: ");\r
+\r
+ cmdstr = "J\r\n";\r
+\r
+ SendComPort(IspEnvironment, cmdstr);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 3, 5000);\r
+\r
+ FormatCommand(cmdstr, temp);\r
+ FormatCommand(Answer, Answer);\r
+ if (strncmp(Answer, temp, strlen(temp)) != 0)\r
+ {\r
+ DebugPrintf(1, "no answer on Read Part Id\n");\r
+ return (NO_ANSWER_RPID);\r
+ }\r
+\r
+ strippedAnswer = (strncmp(Answer, "J\n0\n", 4) == 0) ? Answer + 4 : Answer;\r
+\r
+ Id[0] = strtoul(strippedAnswer, &endPtr, 10);\r
+ Id[1] = 0UL;\r
+ *endPtr = '\0'; /* delete \r\n */\r
+ for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && LPCtypes[i].id != Id[0]; i--)\r
+ /* nothing */;\r
+ IspEnvironment->DetectedDevice = i;\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].EvalId2 != 0)\r
+ {\r
+ /* Read out the second configuration word and run the search again */\r
+ *endPtr = '\n';\r
+ endPtr++;\r
+ if ((endPtr[0] == '\0') || (endPtr[strlen(endPtr)-1] != '\n'))\r
+ {\r
+ /* No or incomplete word 2 */\r
+ ReceiveComPort(IspEnvironment, endPtr, sizeof(Answer)-(endPtr-Answer)-1, &realsize, 1, 100);\r
+ }\r
+\r
+ FormatCommand(endPtr, endPtr);\r
+ if ((*endPtr == '\0') || (*endPtr == '\n'))\r
+ {\r
+ DebugPrintf(1, "incomplete answer on Read Part Id (second configuration word missing)\n");\r
+ return (NO_ANSWER_RPID);\r
+ }\r
+\r
+ Id[1] = strtoul(endPtr, &endPtr, 10);\r
+ *endPtr = '\0'; /* delete \r\n */\r
+\r
+ /* now search the table again */\r
+ for (i = sizeof LPCtypes / sizeof LPCtypes[0] - 1; i > 0 && (LPCtypes[i].id != Id[0] || LPCtypes[i].id2 != Id[1]); i--)\r
+ /* nothing */;\r
+ IspEnvironment->DetectedDevice = i;\r
+ }\r
+ if (IspEnvironment->DetectedDevice == 0) {\r
+ DebugPrintf(2, "unknown");\r
+ }\r
+ else {\r
+ DebugPrintf(2, "LPC%s, %d kiB FLASH / %d kiB SRAM",\r
+ LPCtypes[IspEnvironment->DetectedDevice].Product,\r
+ LPCtypes[IspEnvironment->DetectedDevice].FlashSize,\r
+ LPCtypes[IspEnvironment->DetectedDevice].RAMSize);\r
+ }\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].EvalId2 != 0)\r
+ {\r
+ DebugPrintf(2, " (0x%08lX / 0x%08lX)\n", Id[0], Id[1]);\r
+ }\r
+ else\r
+ {\r
+ DebugPrintf(2, " (0x%08lX)\n", Id[0]);\r
+ }\r
+\r
+ if (!IspEnvironment->DetectOnly)\r
+ {\r
+ // Build up uuencode table\r
+ uuencode_table[0] = 0x60; // 0x20 is translated to 0x60 !\r
+\r
+ for (i = 1; i < 64; i++)\r
+ {\r
+ uuencode_table[i] = (char)(0x20 + i);\r
+ }\r
+\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+ {\r
+ // Patch 0x14, otherwise it is not running and jumps to boot mode\r
+\r
+ ivt_CRC = 0;\r
+\r
+ // Clear the vector at 0x14 so it doesn't affect the checksum:\r
+ for (i = 0; i < 4; i++)\r
+ {\r
+ IspEnvironment->BinaryContent[i + 0x14] = 0;\r
+ }\r
+\r
+ // Calculate a native checksum of the little endian vector table:\r
+ for (i = 0; i < (4 * 8);) {\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++];\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;\r
+ }\r
+\r
+ /* Negate the result and place in the vector at 0x14 as little endian\r
+ * again. The resulting vector table should checksum to 0. */\r
+ ivt_CRC = (unsigned long) (0 - ivt_CRC);\r
+ for (i = 0; i < 4; i++)\r
+ {\r
+ IspEnvironment->BinaryContent[i + 0x14] = (unsigned char)(ivt_CRC >> (8 * i));\r
+ }\r
+\r
+ DebugPrintf(3, "Position 0x14 patched: ivt_CRC = 0x%08lX\n", ivt_CRC);\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ // Patch 0x1C, otherwise it is not running and jumps to boot mode\r
+\r
+ ivt_CRC = 0;\r
+\r
+ // Clear the vector at 0x1C so it doesn't affect the checksum:\r
+ for (i = 0; i < 4; i++)\r
+ {\r
+ IspEnvironment->BinaryContent[i + 0x1C] = 0;\r
+ }\r
+\r
+ // Calculate a native checksum of the little endian vector table:\r
+ for (i = 0; i < (4 * 8);) {\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++];\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++] << 8;\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++] << 16;\r
+ ivt_CRC += IspEnvironment->BinaryContent[i++] << 24;\r
+ }\r
+\r
+ /* Negate the result and place in the vector at 0x1C as little endian\r
+ * again. The resulting vector table should checksum to 0. */\r
+ ivt_CRC = (unsigned long) (0 - ivt_CRC);\r
+ for (i = 0; i < 4; i++)\r
+ {\r
+ IspEnvironment->BinaryContent[i + 0x1C] = (unsigned char)(ivt_CRC >> (8 * i));\r
+ }\r
+\r
+ DebugPrintf(3, "Position 0x1C patched: ivt_CRC = 0x%08lX\n", ivt_CRC);\r
+ }\r
+ else\r
+ {\r
+ DebugPrintf(1, "Internal error: wrong chip variant %d (detected device %d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant, IspEnvironment->DetectedDevice);\r
+ exit(1);\r
+ }\r
+ }\r
+\r
+#if 0\r
+ DebugPrintf(2, "Read Unique ID:\n");\r
+\r
+ cmdstr = "N\r\n";\r
+\r
+ SendComPort(IspEnvironment, cmdstr);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 5,5000);\r
+\r
+ FormatCommand(cmdstr, temp);\r
+ FormatCommand(Answer, Answer);\r
+ if (strncmp(Answer, temp, strlen(temp)) != 0)\r
+ {\r
+ DebugPrintf(1, "no answer on Read Unique ID\n");\r
+ return (NO_ANSWER_RBV);\r
+ }\r
+\r
+ if (strncmp(Answer + strlen(cmdstr), "0\n", 2) == 0)\r
+ {\r
+ strippedAnswer = Answer + strlen(temp) + 2;\r
+ DebugPrintf(2, strippedAnswer);\r
+ }\r
+ else\r
+ {\r
+ DebugPrintf(2, "unknown\n");\r
+ }\r
+#endif // 0\r
+\r
+ /* In case of a download to RAM, use full RAM for downloading\r
+ * set the flash parameters to full RAM also.\r
+ * This makes sure that all code is downloaded as one big sector\r
+ */\r
+\r
+ if ( (IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment))\r
+ &&(IspEnvironment->BinaryOffset + IspEnvironment->BinaryLength <= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+ {\r
+ LPCtypes[IspEnvironment->DetectedDevice].FlashSectors = 1;\r
+ LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize = LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024 - (ReturnValueLpcRamBase(IspEnvironment) - ReturnValueLpcRamStart(IspEnvironment));\r
+ LPCtypes[IspEnvironment->DetectedDevice].SectorTable = SectorTable_RAM;\r
+ SectorTable_RAM[0] = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
+ }\r
+ if (IspEnvironment->DetectOnly)\r
+ return (0);\r
+\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ // XON/XOFF must be switched off for LPC8XX\r
+ // otherwise problem during binary transmission of data to LPC8XX\r
+ DebugPrintf(3, "Switch off XON/XOFF !!!\n");\r
+ ControlXonXoffSerialPort(IspEnvironment, 0);\r
+ }\r
+\r
+ // Start with sector 1 and go upward... Sector 0 containing the interrupt vectors\r
+ // will be loaded last, since it contains a checksum and device will re-enter\r
+ // bootloader mode as long as this checksum is invalid.\r
+ DebugPrintf(2, "Will start programming at Sector 1 if possible, and conclude with Sector 0 to ensure that checksum is written last.\n");\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0] >= IspEnvironment->BinaryLength)\r
+ {\r
+ Sector = 0;\r
+ SectorStart = 0;\r
+ }\r
+ else\r
+ {\r
+ SectorStart = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[0];\r
+ Sector = 1;\r
+ }\r
+\r
+ if (IspEnvironment->WipeDevice == 1)\r
+ {\r
+ DebugPrintf(2, "Wiping Device. ");\r
+\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "P %d %d 0\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "P %d %d\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Prepare-Command\n");\r
+ return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "E %d %d 0\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "E %d %d\r\n", 0, LPCtypes[IspEnvironment->DetectedDevice].FlashSectors-1);\r
+ }\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Erase-Command\n");\r
+ return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
+ }\r
+ DebugPrintf(2, "OK \n");\r
+\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ DebugPrintf(2, "ATTENTION: Only bank A was wiped!!!\n");\r
+ }\r
+ }\r
+ else{\r
+ //no wiping requested: erasing sector 0 first\r
+ DebugPrintf(2, "Erasing sector 0 first, to invalidate checksum. ");\r
+\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "P %d %d 0\r\n", 0, 0);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "P %d %d\r\n", 0, 0);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Prepare-Command\n");\r
+ return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "E %d %d 0\r\n", 0, 0);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "E %d %d\r\n", 0, 0);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Erase-Command\n");\r
+ return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
+ }\r
+ DebugPrintf(2, "OK \n");\r
+ }\r
+ while (1)\r
+ {\r
+ if (Sector >= LPCtypes[IspEnvironment->DetectedDevice].FlashSectors)\r
+ {\r
+ DebugPrintf(1, "Program too large; running out of Flash sectors.\n");\r
+ return (PROGRAM_TOO_LARGE);\r
+ }\r
+\r
+ DebugPrintf(2, "Sector %ld: ", Sector);\r
+ fflush(stdout);\r
+\r
+ if ( (IspEnvironment->BinaryOffset < ReturnValueLpcRamStart(IspEnvironment)) // Skip Erase when running from RAM\r
+ ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+ {\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "P %ld %ld 0\r\n", Sector, Sector);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Prepare-Command (1) (Sector %ld)\n", Sector);\r
+ return (WRONG_ANSWER_PREP + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ DebugPrintf(2, ".");\r
+ fflush(stdout);\r
+ if (IspEnvironment->WipeDevice == 0 && (Sector!=0)) //Sector 0 already erased\r
+ {\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "E %ld %ld 0\r\n", Sector, Sector);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "E %ld %ld\r\n", Sector, Sector);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Erase-Command (Sector %ld)\n", Sector);\r
+ return (WRONG_ANSWER_ERAS + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ DebugPrintf(2, ".");\r
+ fflush(stdout);\r
+ }\r
+ }\r
+\r
+ SectorLength = LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];\r
+ if (SectorLength > IspEnvironment->BinaryLength - SectorStart)\r
+ {\r
+ SectorLength = IspEnvironment->BinaryLength - SectorStart;\r
+ }\r
+\r
+ for (SectorOffset = 0; SectorOffset < SectorLength; SectorOffset += SectorChunk)\r
+ {\r
+ // Check if we are to write only 0xFFs - it would be just a waste of time..\r
+ if (SectorOffset == 0) {\r
+ for (SectorOffset = 0; SectorOffset < SectorLength; ++SectorOffset)\r
+ {\r
+ if (IspEnvironment->BinaryContent[SectorStart + SectorOffset] != 0xFF)\r
+ break;\r
+ }\r
+ if (SectorOffset == SectorLength) // all data contents were 0xFFs\r
+ {\r
+ DebugPrintf(2, "Whole sector contents is 0xFFs, skipping programming.");\r
+ fflush(stdout);\r
+ break;\r
+ }\r
+ SectorOffset = 0; // re-set otherwise\r
+ }\r
+\r
+ if (SectorOffset > 0)\r
+ {\r
+ // Add a visible marker between segments in a sector\r
+ DebugPrintf(2, "|"); /* means: partial segment copied */\r
+ fflush(stdout);\r
+ }\r
+\r
+ // If the Flash ROM sector size is bigger than the number of bytes\r
+ // we can copy from RAM to Flash, we must "chop up" the sector and\r
+ // copy these individually.\r
+ // This is especially needed in the case where a Flash sector is\r
+ // bigger than the amount of SRAM.\r
+ SectorChunk = SectorLength - SectorOffset;\r
+ if (SectorChunk > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)\r
+ {\r
+ SectorChunk = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
+ }\r
+\r
+ // Write multiple of 45 * 4 Byte blocks to RAM, but copy maximum of on sector to Flash\r
+ // In worst case we transfer up to 180 byte too much to RAM\r
+ // but then we can always use full 45 byte blocks and length is multiple of 4\r
+ CopyLength = SectorChunk;\r
+\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+ {\r
+ if ((CopyLength % (45 * 4)) != 0)\r
+ {\r
+ CopyLength += ((45 * 4) - (CopyLength % (45 * 4)));\r
+ }\r
+ }\r
+\r
+ sprintf(tmpString, "W %ld %ld\r\n", ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Write-Command\n");\r
+ return (WRONG_ANSWER_WRIT + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ DebugPrintf(2, ".");\r
+ fflush(stdout);\r
+\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+ {\r
+ block_CRC = 0;\r
+ Line = 0;\r
+\r
+ // Transfer blocks of 45 * 4 bytes to RAM\r
+ for (Pos = SectorStart + SectorOffset; (Pos < SectorStart + SectorOffset + CopyLength) && (Pos < IspEnvironment->BinaryLength); Pos += (45 * 4))\r
+ {\r
+ for (Block = 0; Block < 4; Block++) // Each block 45 bytes\r
+ {\r
+ DebugPrintf(2, ".");\r
+ fflush(stdout);\r
+\r
+#if defined INTEGRATED_IN_WIN_APP\r
+ // inform the calling application about having written another chuck of data\r
+ AppWritten(45);\r
+#endif\r
+\r
+ // Uuencode one 45 byte block\r
+ tmpStringPos = 0;\r
+\r
+#if !defined COMPILE_FOR_LPC21\r
+ sendbuf[Line][tmpStringPos++] = (char)(' ' + 45); // Encode Length of block\r
+#else\r
+ tmpString[tmpStringPos++] = (char)(' ' + 45); // Encode Length of block\r
+#endif\r
+\r
+ for (BlockOffset = 0; BlockOffset < 45; BlockOffset++)\r
+ {\r
+ if ( (IspEnvironment->BinaryOffset < ReturnValueLpcRamStart(IspEnvironment))\r
+ ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+ { // Flash: use full memory\r
+ c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset];\r
+ }\r
+ else\r
+ { // RAM: Skip first 0x200 bytes, these are used by the download program in LPC21xx\r
+ c = IspEnvironment->BinaryContent[Pos + Block * 45 + BlockOffset + 0x200];\r
+ }\r
+\r
+ block_CRC += c;\r
+\r
+ k = (k << 8) + (c & 255);\r
+\r
+ if ((BlockOffset % 3) == 2) // Collecting always 3 Bytes, then do processing in 4 Bytes\r
+ {\r
+#if !defined COMPILE_FOR_LPC21\r
+ sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 18) & 63];\r
+ sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 12) & 63];\r
+ sendbuf[Line][tmpStringPos++] = uuencode_table[(k >> 6) & 63];\r
+ sendbuf[Line][tmpStringPos++] = uuencode_table[ k & 63];\r
+#else\r
+ tmpString[tmpStringPos++] = uuencode_table[(k >> 18) & 63];\r
+ tmpString[tmpStringPos++] = uuencode_table[(k >> 12) & 63];\r
+ tmpString[tmpStringPos++] = uuencode_table[(k >> 6) & 63];\r
+ tmpString[tmpStringPos++] = uuencode_table[ k & 63];\r
+#endif\r
+ }\r
+ }\r
+\r
+\r
+#if !defined COMPILE_FOR_LPC21\r
+ sendbuf[Line][tmpStringPos++] = '\r';\r
+ sendbuf[Line][tmpStringPos++] = '\n';\r
+ sendbuf[Line][tmpStringPos++] = 0;\r
+\r
+ SendComPort(IspEnvironment, sendbuf[Line]);\r
+ // receive only for debug proposes\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
+ FormatCommand(sendbuf[Line], tmpString);\r
+ FormatCommand(Answer, Answer);\r
+ if (strncmp(Answer, tmpString, strlen(tmpString)) != 0)\r
+ {\r
+ DebugPrintf(1, "Error on writing data (1)\n");\r
+ return (ERROR_WRITE_DATA);\r
+ }\r
+#else\r
+ tmpString[tmpStringPos++] = '\r';\r
+ tmpString[tmpStringPos++] = '\n';\r
+ tmpString[tmpStringPos++] = 0;\r
+\r
+ SendComPort(IspEnvironment, tmpString);\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
+ FormatCommand(tmpString, tmpString);\r
+ FormatCommand(Answer, Answer);\r
+ if (strncmp(Answer, tmpString, tmpStringPos) != 0)\r
+ {\r
+ DebugPrintf(1, "Error on writing data (1)\n");\r
+ return (ERROR_WRITE_DATA);\r
+ }\r
+#endif\r
+\r
+ Line++;\r
+\r
+ DebugPrintf(3, "Line = %d\n", Line);\r
+\r
+ if (Line == 20)\r
+ {\r
+#if !defined COMPILE_FOR_LPC21\r
+ for (repeat = 0; repeat < 3; repeat++)\r
+ {\r
+\r
+ // DebugPrintf(1, "block_CRC = %ld\n", block_CRC);\r
+\r
+ sprintf(tmpString, "%ld\r\n", block_CRC);\r
+\r
+ SendComPort(IspEnvironment, tmpString);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);\r
+\r
+ sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+\r
+ FormatCommand(tmpString, tmpString);\r
+ FormatCommand(Answer, Answer);\r
+ if (strcmp(Answer, tmpString) != 0)\r
+ {\r
+ for (i = 0; i < Line; i++)\r
+ {\r
+ SendComPort(IspEnvironment, sendbuf[i]);\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);\r
+ }\r
+ }\r
+ else\r
+ break;\r
+ }\r
+\r
+ if (repeat >= 3)\r
+ {\r
+ DebugPrintf(1, "Error on writing block_CRC (1)\n");\r
+ return (ERROR_WRITE_CRC);\r
+ }\r
+#else\r
+ // DebugPrintf(1, "block_CRC = %ld\n", block_CRC);\r
+ sprintf(tmpString, "%ld\r\n", block_CRC);\r
+ SendComPort(IspEnvironment, tmpString);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+ sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+ FormatCommand(tmpString, tmpString);\r
+ FormatCommand(Answer, Answer);\r
+ if (strcmp(Answer, tmpString) != 0)\r
+ {\r
+ DebugPrintf(1, "Error on writing block_CRC (2)\n");\r
+ return (ERROR_WRITE_CRC);\r
+ }\r
+#endif\r
+ Line = 0;\r
+ block_CRC = 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Line != 0)\r
+ {\r
+#if !defined COMPILE_FOR_LPC21\r
+ for (repeat = 0; repeat < 3; repeat++)\r
+ {\r
+ sprintf(tmpString, "%ld\r\n", block_CRC);\r
+\r
+ SendComPort(IspEnvironment, tmpString);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+ sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+\r
+ FormatCommand(tmpString, tmpString);\r
+ FormatCommand(Answer, Answer);\r
+ if (strcmp(Answer, tmpString) != 0)\r
+ {\r
+ for (i = 0; i < Line; i++)\r
+ {\r
+ SendComPort(IspEnvironment, sendbuf[i]);\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1,5000);\r
+ }\r
+ }\r
+ else\r
+ break;\r
+ }\r
+\r
+ if (repeat >= 3)\r
+ {\r
+ DebugPrintf(1, "Error on writing block_CRC (3)\n");\r
+ return (ERROR_WRITE_CRC2);\r
+ }\r
+#else\r
+ sprintf(tmpString, "%ld\r\n", block_CRC);\r
+ SendComPort(IspEnvironment, tmpString);\r
+\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);\r
+\r
+ sprintf(tmpString, "%ld\nOK\n", block_CRC);\r
+ FormatCommand(tmpString, tmpString);\r
+ FormatCommand(Answer, Answer);\r
+ if (strcmp(Answer, tmpString) != 0)\r
+ {\r
+ DebugPrintf(1, "Error on writing block_CRC (4)\n");\r
+ return (ERROR_WRITE_CRC2);\r
+ }\r
+#endif\r
+ }\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ unsigned char BigAnswer[4096];\r
+ unsigned long CopyLengthPartialOffset = 0;\r
+ unsigned long CopyLengthPartialRemainingBytes;\r
+\r
+ while(CopyLengthPartialOffset < CopyLength)\r
+ {\r
+ CopyLengthPartialRemainingBytes = CopyLength - CopyLengthPartialOffset;\r
+ if(CopyLengthPartialRemainingBytes > 256)\r
+ {\r
+ // There seems to be an error in LPC812:\r
+ // When too much bytes are written at high speed,\r
+ // bytes get lost\r
+ // Workaround: Use smaller blocks\r
+ CopyLengthPartialRemainingBytes = 256;\r
+ }\r
+\r
+ SendComPortBlock(IspEnvironment, &IspEnvironment->BinaryContent[SectorStart + SectorOffset + CopyLengthPartialOffset], CopyLengthPartialRemainingBytes);\r
+\r
+ if (ReceiveComPortBlockComplete(IspEnvironment, &BigAnswer, CopyLengthPartialRemainingBytes, 10000) != 0)\r
+ {\r
+ return (ERROR_WRITE_DATA);\r
+ }\r
+\r
+ if(memcmp(&IspEnvironment->BinaryContent[SectorStart + SectorOffset + CopyLengthPartialOffset], BigAnswer, CopyLengthPartialRemainingBytes))\r
+ {\r
+ return (ERROR_WRITE_DATA);\r
+ }\r
+\r
+ CopyLengthPartialOffset += CopyLengthPartialRemainingBytes;\r
+ }\r
+ }\r
+\r
+ if ( (IspEnvironment->BinaryOffset < ReturnValueLpcRamStart(IspEnvironment))\r
+ ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+ {\r
+ // Prepare command must be repeated before every write\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ // TODO: Quick and dirty hack to address bank 0\r
+ sprintf(tmpString, "P %ld %ld 0\r\n", Sector, Sector);\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "P %ld %ld\r\n", Sector, Sector);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Prepare-Command (2) (Sector %ld)\n", Sector);\r
+ return (WRONG_ANSWER_PREP2 + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ // Round CopyLength up to one of the following values: 512, 1024,\r
+ // 4096, 8192; but do not exceed the maximum copy size (usually\r
+ // 8192, but chip-dependent)\r
+ if (CopyLength < 512)\r
+ {\r
+ CopyLength = 512;\r
+ }\r
+ else if (SectorLength < 1024)\r
+ {\r
+ CopyLength = 1024;\r
+ }\r
+ else if (SectorLength < 4096)\r
+ {\r
+ CopyLength = 4096;\r
+ }\r
+ else\r
+ {\r
+ CopyLength = 8192;\r
+ }\r
+ if (CopyLength > (unsigned)LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize)\r
+ {\r
+ CopyLength = LPCtypes[IspEnvironment->DetectedDevice].MaxCopySize;\r
+ }\r
+\r
+ sprintf(tmpString, "C %ld %ld %ld\r\n", IspEnvironment->BinaryOffset + SectorStart + SectorOffset, ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Copy-Command\n");\r
+ return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));\r
+ }\r
+\r
+ if (IspEnvironment->Verify)\r
+ {\r
+\r
+ //Avoid compare first 64 bytes.\r
+ //Because first 64 bytes are re-mapped to flash boot sector,\r
+ //and the compare result may not be correct.\r
+ if (SectorStart + SectorOffset<64)\r
+ {\r
+ sprintf(tmpString, "M %d %ld %ld\r\n", 64, ReturnValueLpcRamBase(IspEnvironment) + (64 - SectorStart - SectorOffset), CopyLength-(64 - SectorStart - SectorOffset));\r
+ }\r
+ else\r
+ {\r
+ sprintf(tmpString, "M %ld %ld %ld\r\n", SectorStart + SectorOffset, ReturnValueLpcRamBase(IspEnvironment), CopyLength);\r
+ }\r
+\r
+ if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on Compare-Command\n");\r
+ return (WRONG_ANSWER_COPY + GetAndReportErrorNumber(Answer));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ DebugPrintf(2, "\n");\r
+ fflush(stdout);\r
+\r
+ if ((SectorStart + SectorLength) >= IspEnvironment->BinaryLength && Sector!=0)\r
+ {\r
+ Sector = 0;\r
+ SectorStart = 0;\r
+ }\r
+ else if (Sector == 0) {\r
+ break;\r
+ }\r
+ else {\r
+ SectorStart += LPCtypes[IspEnvironment->DetectedDevice].SectorTable[Sector];\r
+ Sector++;\r
+ }\r
+ }\r
+\r
+ tDoneUpload = time(NULL);\r
+ if (IspEnvironment->Verify)\r
+ DebugPrintf(2, "Download Finished and Verified correct... taking %d seconds\n", tDoneUpload - tStartUpload);\r
+ else\r
+ DebugPrintf(2, "Download Finished... taking %d seconds\n", tDoneUpload - tStartUpload);\r
+\r
+ // For LPC18xx set boot bank to 0\r
+ if (LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ if (!SendAndVerify(IspEnvironment, "S 0\r\n", Answer, sizeof Answer))\r
+ {\r
+ DebugPrintf(1, "Wrong answer on SetActiveBootFlashBank-Command\n");\r
+ return (WRONG_ANSWER_BTBNK + GetAndReportErrorNumber(Answer));\r
+ }\r
+ }\r
+\r
+ if(IspEnvironment->DoNotStart == 0)\r
+ {\r
+ DebugPrintf(2, "Now launching the brand new code\n");\r
+ fflush(stdout);\r
+\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+ {\r
+ sprintf(tmpString, "G %ld A\r\n", IspEnvironment->StartAddress);\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+ {\r
+ sprintf(tmpString, "G %ld T\r\n", IspEnvironment->StartAddress & ~1);\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ sprintf(tmpString, "G 0 T\r\n");\r
+ }\r
+ else\r
+ {\r
+ DebugPrintf(1, "Internal Error %s %d\n", __FILE__, __LINE__);\r
+ exit(1);\r
+ }\r
+\r
+ SendComPort(IspEnvironment, tmpString); //goto 0 : run this fresh new downloaded code code\r
+ if ( (IspEnvironment->BinaryOffset < ReturnValueLpcRamStart(IspEnvironment))\r
+ ||(IspEnvironment->BinaryOffset >= ReturnValueLpcRamStart(IspEnvironment)+(LPCtypes[IspEnvironment->DetectedDevice].RAMSize*1024)))\r
+ { // Skip response on G command - show response on Terminal instead\r
+ ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2, 5000);\r
+ /* the reply string is frequently terminated with a -1 (EOF) because the\r
+ * connection gets broken; zero-terminate the string ourselves\r
+ */\r
+ while (realsize > 0 && ((signed char) Answer[(int)realsize - 1]) < 0)\r
+ realsize--;\r
+ Answer[(int)realsize] = '\0';\r
+ /* Better to check only the first 9 chars instead of complete receive buffer,\r
+ * because the answer can contain the output by the started programm\r
+ */\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+ {\r
+ sprintf(ExpectedAnswer, "G %ld A\n0", IspEnvironment->StartAddress);\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX ||\r
+ LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+ {\r
+ sprintf(ExpectedAnswer, "G %ld T\n0", IspEnvironment->StartAddress & ~1);\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ sprintf(ExpectedAnswer, "G 0 T\n0");\r
+ }\r
+ else\r
+ {\r
+ DebugPrintf(1, "Internal Error %s %d\n", __FILE__, __LINE__);\r
+ exit(1);\r
+ }\r
+\r
+ FormatCommand(Answer, Answer);\r
+ if (realsize == 0 || strncmp((const char *)Answer, /*cmdstr*/ExpectedAnswer, strlen(/*cmdstr*/ExpectedAnswer)) != 0)\r
+ {\r
+ DebugPrintf(2, "Failed to run the new downloaded code: ");\r
+ return (FAILED_RUN + GetAndReportErrorNumber(Answer));\r
+ }\r
+ }\r
+\r
+ fflush(stdout);\r
+ }\r
+ return (0);\r
+}\r
+#endif // LPC_SUPPORT\r
+\r
+\r
+unsigned long ReturnValueLpcRamStart(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+ {\r
+ return LPC_RAMSTART_LPC43XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+ {\r
+ return LPC_RAMSTART_LPC2XXX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ return LPC_RAMSTART_LPC18XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX)\r
+ {\r
+ return LPC_RAMSTART_LPC17XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX)\r
+ {\r
+ return LPC_RAMSTART_LPC13XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+ {\r
+ return LPC_RAMSTART_LPC11XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ return LPC_RAMSTART_LPC8XX;\r
+ }\r
+ DebugPrintf(1, "Error in ReturnValueLpcRamStart (%d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant);\r
+ exit(1);\r
+}\r
+\r
+\r
+unsigned long ReturnValueLpcRamBase(ISP_ENVIRONMENT *IspEnvironment)\r
+{\r
+ if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC43XX)\r
+ {\r
+ return LPC_RAMBASE_LPC43XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC2XXX)\r
+ {\r
+ return LPC_RAMBASE_LPC2XXX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC18XX)\r
+ {\r
+ return LPC_RAMBASE_LPC18XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC17XX)\r
+ {\r
+ return LPC_RAMBASE_LPC17XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC13XX)\r
+ {\r
+ return LPC_RAMBASE_LPC13XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC11XX)\r
+ {\r
+ return LPC_RAMBASE_LPC11XX;\r
+ }\r
+ else if(LPCtypes[IspEnvironment->DetectedDevice].ChipVariant == CHIP_VARIANT_LPC8XX)\r
+ {\r
+ return LPC_RAMBASE_LPC8XX;\r
+ }\r
+ DebugPrintf(1, "Error in ReturnValueLpcRamBase (%d)\n", LPCtypes[IspEnvironment->DetectedDevice].ChipVariant);\r
+ exit(1);\r
+}\r