root/trunk/tools/lpc21isp/adprog.c

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

Update lpc21isp

Line 
1/******************************************************************************
2
3Project:           Portable command line ISP for Philips LPC2000 family
4                   and Analog Devices ADUC70xx
5
6Filename:          adprog.c
7
8Compiler:          Microsoft VC 6/7, GCC Cygwin, GCC Linux, GCC ARM ELF
9
10Author:            Martin Maurer (Martin.Maurer@clibb.de)
11
12Copyright:         (c) Martin Maurer 2003-2008, All rights reserved
13Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.com
14
15    This file is part of lpc21isp.
16
17    lpc21isp is free software: you can redistribute it and/or modify
18    it under the terms of the GNU Lesser General Public License as published by
19    the Free Software Foundation, either version 3 of the License, or
20    any later version.
21
22    lpc21isp is distributed in the hope that it will be useful,
23    but WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25    GNU Lesser General Public License for more details.
26
27    You should have received a copy of the GNU Lesser General Public License
28    and GNU General Public License along with lpc21isp.
29    If not, see <http://www.gnu.org/licenses/>.
30*/
31
32#if defined(_WIN32)
33#if !defined __BORLANDC__
34#include "StdAfx.h"
35#endif
36#endif // defined(_WIN32)
37#include "lpc21isp.h"
38
39#ifdef AD_SUPPORT
40#include "adprog.h"
41
42/***************************** AnalogDevicesSync ************************/
43/**  Attempt to synchronize with an Analog Device ARM micro.  Sends a
44backspace and reads back the microcontrollers response.  Performs
45multiple retries. Exits the program on error, returns to caller in the
46case of success.
47*/
48static void AnalogDevicesSync(ISP_ENVIRONMENT *IspEnvironment)
49{
50    BINARY sync;                        /* Holds sync command.          */
51    AD_SYNC_RESPONSE response;          /* Response from micro.         */
52    int sync_attempts;                  /* Number of retries.           */
53
54    /*  Make sure we don't read garbage later instead of the        */
55    /* response we expect from the micro.                           */
56    ClearSerialPortBuffers(IspEnvironment);
57
58    DebugPrintf(2, "Synchronizing\n"); /* Progress report.             */
59
60    sync = ANALOG_DEVICES_SYNC_CHAR;    /* Build up sync command.       */
61
62    /*  Perform the actual sync attempt.  First send the sync       */
63    /* character, the attempt to read back the response.  For the   */
64    /* AD ARM micro this is a fixed length block.  If response is   */
65    /* received attempt to validate it by comparing the first       */
66    /* characters to those expected.  If the received block does    */
67    /* not validate or is incomplete empty the serial buffer and    */
68    /* retry.                                                       */
69    for (sync_attempts = 0; sync_attempts < 5; sync_attempts++)
70    {
71        SendComPortBlock(IspEnvironment, &sync, 1);
72
73        if (ReceiveComPortBlockComplete(IspEnvironment, &response, sizeof(response),
74            500) == 0)
75        {
76
77            if (memcmp(response.product_id, ANALOG_DEVICES_SYNC_RESPONSE,
78                ANALOG_DEVICES_SYNC_SIZE) == 0)
79            {
80                return;
81            }
82            else
83            {
84                DumpString(3, &response, sizeof(response),
85                    "Unexpected response to sync attempt ");
86            }
87        }
88        else
89        {
90            DebugPrintf(3, "No (or incomplete) answer on sync attempt\n");
91        }
92
93        ClearSerialPortBuffers(IspEnvironment);
94    }
95
96    DebugPrintf(1, "No (or unacceptable) answer on sync attempt\n");
97    exit(4);
98}
99
100typedef struct {
101    char start1;
102    char start2;
103    BINARY bytes;
104    char cmd;
105    BINARY address_h;
106    BINARY address_u;
107    BINARY address_m;
108    BINARY address_l;
109    BINARY data[251];
110} AD_PACKET;
111
112/***************************** AnalogDevicesFormPacket ******************/
113/**  Create an Analog Devices communication packet from the constituent
114elements.
115\param [in] cmd The command being sent, one of 'E' for erase, 'W' for
116write, 'V' for verify or 'R' for run..
117\param [in] no_bytes the number of data bytes to send with the command in
118the packet.
119\param [in] address the address to apply the command to.
120\param [in] data the data to send with the packet, may be null if no_bytes
121is zero.
122\param[out] packet that will be filled.
123*/
124static void AnalogDevicesFormPacket(ISP_ENVIRONMENT *IspEnvironment,
125                                                char cmd, int no_bytes, unsigned int address,
126                                                const void *data, AD_PACKET *packet)
127{
128    BINARY checksum;
129    const BINARY *data_in;
130    int i;
131
132    (void)IspEnvironment; /* never used in this function */
133
134    /*  Some sanity checking on the arguments.  These should only   */
135    /* fail if there is a bug in the caller.                        */
136    /*  Check 1) that the number of data bytes is in an acceptable  */
137    /* range, 2) that we have a non-null pointer if data is being   */
138    /* put in the packet and 3) that we have a non-null pointer to  */
139    /* the packet to be filled. We just exit with an error message  */
140    /* if any of these tests fail.                                  */
141    if ((no_bytes < 0) || (no_bytes > 250))
142    {
143        DebugPrintf(1,
144            "The number of bytes (%d) passed to FormPacket is invalid.\n",
145            no_bytes);
146        exit(-1);
147    }
148    if ((data == 0) && (no_bytes != 0))
149    {
150        DebugPrintf(1,
151            "A null pointer to data paased to FormPacket when data was expected.\n");
152        exit(-1);
153    }
154    if (packet == 0)
155    {
156        DebugPrintf(1,
157            "A null packet pointer was passed to FormPacket.\n");
158        exit(-1);
159    }
160
161    checksum = 0;               /*  Checksum starts at zero.            */
162
163    data_in = (BINARY*) data;             /*  Pointer pun so we can walk through  */
164    /* the data.                            */
165
166    packet->start1 = 0x7;       /*  The start of the packet is constant.*/
167    packet->start2 = 0xE;
168
169    /*  Fill in the rest of the packet and calculate the checksum   */
170    /* as we go.                                                    */
171
172    /* The number of bytes is the number of data bytes + the        */
173    /* address bytes + the command byte.                            */
174    packet->bytes = (BINARY)(no_bytes + 5);
175
176    checksum += packet->bytes;
177
178    /*  The command for the packet being sent.  No error checking   */
179    /* done on this.                                                */
180    packet->cmd = cmd;
181
182    checksum += cmd;
183
184    /*  Now break up the address and place in the proper packet     */
185    /* locations.                                                   */
186    packet->address_l = (BINARY)(address & 0xFF);
187    packet->address_m = (BINARY)((address >> 8) & 0xFF);
188    packet->address_u = (BINARY)((address >> 16) & 0xFF);
189    packet->address_h = (BINARY)((address >> 24) & 0xFF);
190
191    checksum += packet->address_l;
192    checksum += packet->address_m;
193    checksum += packet->address_u;
194    checksum += packet->address_h;
195
196    /*  Copy the data bytes into the packet.  We could use memcpy   */
197    /* but we have to calculate the checksum anyway.                */
198    for (i = 0; i < no_bytes; i++)
199    {
200        packet->data[i] = data_in[i];
201        checksum += data_in[i];
202    }
203
204    /*  Finally, add the checksum to the end of the packet.         */
205    packet->data[i] = (BINARY)-checksum;
206}
207
208/***************************** AnalogDevicesSendPacket ******************/
209/**  Send a previously form Analog Devices communication.  Retry a
210couple of times if needed but fail by exiting the program if no ACK is
211forthcoming.
212\param [in] packet the packet to send.
213*/
214static void AnalogDevicesSendPacket(ISP_ENVIRONMENT *IspEnvironment,
215                                                const AD_PACKET * packet)
216{
217    BINARY response;
218    int retry = 0;
219
220    do {
221        retry++;
222
223        /*  Make sure we don't read garbage later instead of    */
224        /* the response we expect from the micro.               */
225        ClearSerialPortBuffers(IspEnvironment);
226
227        /*  Send the packet, the size is the number of data     */
228        /* bytes in the packet plus 3 bytes worth of header     */
229        /* plus checksum.                                       */
230        SendComPortBlock(IspEnvironment, packet, packet->bytes + 4);
231
232        /*  Receive the response and check, return to caller    */
233        /* if successful.                                       */
234        if (ReceiveComPortBlockComplete(IspEnvironment, &response, 1, 5000) == 0)
235        {
236            if (response == ANALOG_DEVICES_ACK)
237            {
238                DebugPrintf(3, "Packet Sent\n");
239                return;
240            }
241            if (response != ANALOG_DEVICES_NAK)
242            {
243                DebugPrintf(3, "Unexpected response to packet (%x)\n", (int)response);
244            }
245            DebugPrintf(2, "*");
246        }
247    } while (retry < 3);
248
249    DebugPrintf(1, "Send packet failed\n");
250    exit(-1);
251}
252
253/***************************** AnalogDevicesErase ***********************/
254/**  Erase the Analog Devices micro.  We take the simple way out and
255just erase the whole thing.
256*/
257static void AnalogDevicesErase(ISP_ENVIRONMENT *IspEnvironment)
258{
259    BINARY pages;
260    AD_PACKET packet;
261
262    pages = 0;
263    DebugPrintf(2, "Erasing .. ");
264    AnalogDevicesFormPacket(IspEnvironment, 'E', 1, 0, &pages, &packet);
265    AnalogDevicesSendPacket(IspEnvironment, &packet);
266    DebugPrintf(2, "Erased\n");
267}
268
269#define AD_PACKET_SIZE (250)
270
271/***************************** AnalogDevicesWrite ***********************/
272/**  Write the program.
273\param [in] data the program to download to the micro.
274\param [in] address where to start placing the program.
275\param [in] bytes the size of the progrm to download.
276*/
277static void AnalogDevicesWrite(ISP_ENVIRONMENT *IspEnvironment,
278                                         const void *data, long address, size_t bytes)
279{
280    AD_PACKET packet;
281    const BINARY *prog_data;
282
283    DebugPrintf(2, "Writing %d bytes ", bytes);
284    prog_data = (const BINARY*) data;
285    while (bytes > AD_PACKET_SIZE)
286    {
287        AnalogDevicesFormPacket(IspEnvironment, 'W', AD_PACKET_SIZE, address, prog_data, &packet);
288        AnalogDevicesSendPacket(IspEnvironment, &packet);
289        address += AD_PACKET_SIZE;
290        prog_data += AD_PACKET_SIZE;
291        bytes -= AD_PACKET_SIZE;
292        DebugPrintf(2, ".");
293    }
294    if (bytes > 0)
295    {
296        AnalogDevicesFormPacket(IspEnvironment, 'W', bytes, address, prog_data, &packet);
297        AnalogDevicesSendPacket(IspEnvironment, &packet);
298        DebugPrintf(2, ".");
299    }
300}
301
302/***************************** AnalogDevicesDownload ********************/
303/**  Perform the download into an Analog Devices micro.  As a quick and
304* dirty hack against flash relocations at 0x80000
305* \return 0 if ok, error code else
306* \ToDo: possible to implement the return value instead of calling
307* exit() in sub-functions
308*/
309int AnalogDevicesDownload(ISP_ENVIRONMENT *IspEnvironment)
310{
311    AnalogDevicesSync(IspEnvironment);
312    AnalogDevicesErase(IspEnvironment);
313    if (IspEnvironment->BinaryLength > 0x80000)
314    {
315        DebugPrintf(2, "Note:  Flash remapped 0x80000 to 0.\n");
316        AnalogDevicesWrite(IspEnvironment, IspEnvironment->BinaryContent + 0x80000, 0, IspEnvironment->BinaryLength-0x80000);
317    }
318    else
319    {
320        AnalogDevicesWrite(IspEnvironment, IspEnvironment->BinaryContent, 0, IspEnvironment->BinaryLength);
321    }
322    return (0);
323}
324#endif // AD_SUPPORT
Note: See TracBrowser for help on using the browser.