Vous êtes sur la page 1sur 6

.

*/

#if defined(_WIN32)
#if !defined __BORLANDC__
#include "StdAfx.h"
#endif
#endif // defined(_WIN32)
#include "lpc21isp.h"

#ifdef AD_SUPPORT
#include "adprog.h"

/***************************** AnalogDevicesSync ************************/


/** Attempt to synchronize with an Analog Device ARM micro. Sends a
backspace and reads back the microcontrollers response. Performs
multiple retries. Exits the program on error, returns to caller in the
case of success.
*/
static void AnalogDevicesSync(ISP_ENVIRONMENT *IspEnvironment)
{
BINARY sync; /* Holds sync command. */
AD_SYNC_RESPONSE response; /* Response from micro. */
int sync_attempts; /* Number of retries. */

/* Make sure we don't read garbage later instead of the */


/* response we expect from the micro. */
ClearSerialPortBuffers(IspEnvironment);

DebugPrintf(2, "Synchronizing\n"); /* Progress report. */

sync = ANALOG_DEVICES_SYNC_CHAR; /* Build up sync command. */

/* Perform the actual sync attempt. First send the sync */


/* character, the attempt to read back the response. For the */
/* AD ARM micro this is a fixed length block. If response is */
/* received attempt to validate it by comparing the first */
/* characters to those expected. If the received block does */
/* not validate or is incomplete empty the serial buffer and */
/* retry. */
for (sync_attempts = 0; sync_attempts < 5; sync_attempts++)
{
SendComPortBlock(IspEnvironment, &sync, 1);

if (ReceiveComPortBlockComplete(IspEnvironment, &response, sizeof(response),


500) == 0)
{

if (memcmp(response.product_id, ANALOG_DEVICES_SYNC_RESPONSE,
ANALOG_DEVICES_SYNC_SIZE) == 0)
{
return;
}
else
{
DumpString(3, &response, sizeof(response),
"Unexpected response to sync attempt ");
}
}
else
{
DebugPrintf(3, "No (or incomplete) answer on sync attempt\n");
}

ClearSerialPortBuffers(IspEnvironment);
}

DebugPrintf(1, "No (or unacceptable) answer on sync attempt\n");


exit(4);
}

typedef struct {
char start1;
char start2;
BINARY bytes;
char cmd;
BINARY address_h;
BINARY address_u;
BINARY address_m;
BINARY address_l;
BINARY data[251];
} AD_PACKET;

/***************************** AnalogDevicesFormPacket ******************/


/** Create an Analog Devices communication packet from the constituent
elements.
\param [in] cmd The command being sent, one of 'E' for erase, 'W' for
write, 'V' for verify or 'R' for run..
\param [in] no_bytes the number of data bytes to send with the command in
the packet.
\param [in] address the address to apply the command to.
\param [in] data the data to send with the packet, may be null if no_bytes
is zero.
\param[out] packet that will be filled.
*/
static void AnalogDevicesFormPacket(ISP_ENVIRONMENT *IspEnvironment,
char cmd, int no_bytes, unsigned int address,
const void *data, AD_PACKET *packet)
{
BINARY checksum;
const BINARY *data_in;
int i;

(void)IspEnvironment; /* never used in this function */


/* Some sanity checking on the arguments. These should only */
/* fail if there is a bug in the caller. */
/* Check 1) that the number of data bytes is in an acceptable */
/* range, 2) that we have a non-null pointer if data is being */
/* put in the packet and 3) that we have a non-null pointer to */
/* the packet to be filled. We just exit with an error message */
/* if any of these tests fail. */
if ((no_bytes < 0) || (no_bytes > 250))
{
DebugPrintf(1,
"The number of bytes (%d) passed to FormPacket is invalid.\n",
no_bytes);
exit(-1);
}
if ((data == 0) && (no_bytes != 0))
{
DebugPrintf(1,
"A null pointer to data paased to FormPacket when data was expected.\n");
exit(-1);
}
if (packet == 0)
{
DebugPrintf(1,
"A null packet pointer was passed to FormPacket.\n");
exit(-1);
}

checksum = 0; /* Checksum starts at zero. */

data_in = (BINARY*) data; /* Pointer pun so we can walk through */


/* the data. */

packet->start1 = 0x7; /* The start of the packet is constant.*/


packet->start2 = 0xE;

/* Fill in the rest of the packet and calculate the checksum */


/* as we go. */

/* The number of bytes is the number of data bytes + the */


/* address bytes + the command byte. */
packet->bytes = (BINARY)(no_bytes + 5);

checksum += packet->bytes;

/* The command for the packet being sent. No error checking */


/* done on this. */
packet->cmd = cmd;

checksum += cmd;

/* Now break up the address and place in the proper packet */


/* locations. */
packet->address_l = (BINARY)(address & 0xFF);
packet->address_m = (BINARY)((address >> 8) & 0xFF);
packet->address_u = (BINARY)((address >> 16) & 0xFF);
packet->address_h = (BINARY)((address >> 24) & 0xFF);

checksum += packet->address_l;
checksum += packet->address_m;
checksum += packet->address_u;
checksum += packet->address_h;

/* Copy the data bytes into the packet. We could use memcpy */
/* but we have to calculate the checksum anyway. */
for (i = 0; i < no_bytes; i++)
{
packet->data[i] = data_in[i];
checksum += data_in[i];
}

/* Finally, add the checksum to the end of the packet. */


packet->data[i] = (BINARY)-checksum;
}

/***************************** AnalogDevicesSendPacket ******************/


/** Send a previously form Analog Devices communication. Retry a
couple of times if needed but fail by exiting the program if no ACK is
forthcoming.
\param [in] packet the packet to send.
*/
static void AnalogDevicesSendPacket(ISP_ENVIRONMENT *IspEnvironment,
const AD_PACKET * packet)
{
BINARY response;
int retry = 0;

do {
retry++;

/* Make sure we don't read garbage later instead of */


/* the response we expect from the micro. */
ClearSerialPortBuffers(IspEnvironment);

/* Send the packet, the size is the number of data */


/* bytes in the packet plus 3 bytes worth of header */
/* plus checksum. */
SendComPortBlock(IspEnvironment, packet, packet->bytes + 4);

/* Receive the response and check, return to caller */


/* if successful. */
if (ReceiveComPortBlockComplete(IspEnvironment, &response, 1, 5000) == 0)
{
if (response == ANALOG_DEVICES_ACK)
{
DebugPrintf(3, "Packet Sent\n");
return;
}
if (response != ANALOG_DEVICES_NAK)
{
DebugPrintf(3, "Unexpected response to packet (%x)\n", (int)response);
}
DebugPrintf(2, "*");
}
} while (retry < 3);

DebugPrintf(1, "Send packet failed\n");


exit(-1);
}

/***************************** AnalogDevicesErase ***********************/


/** Erase the Analog Devices micro. We take the simple way out and
just erase the whole thing.
*/
static void AnalogDevicesErase(ISP_ENVIRONMENT *IspEnvironment)
{
BINARY pages;
AD_PACKET packet;

pages = 0;
DebugPrintf(2, "Erasing .. ");
AnalogDevicesFormPacket(IspEnvironment, 'E', 1, 0, &pages, &packet);
AnalogDevicesSendPacket(IspEnvironment, &packet);
DebugPrintf(2, "Erased\n");
}

#define AD_PACKET_SIZE (250)

/***************************** AnalogDevicesWrite ***********************/


/** Write the program.
\param [in] data the program to download to the micro.
\param [in] address where to start placing the program.
\param [in] bytes the size of the progrm to download.
*/
static void AnalogDevicesWrite(ISP_ENVIRONMENT *IspEnvironment,
const void *data, long address, size_t bytes)
{
AD_PACKET packet;
const BINARY *prog_data;

DebugPrintf(2, "Writing %d bytes ", bytes);


prog_data = (const BINARY*) data;
while (bytes > AD_PACKET_SIZE)
{
AnalogDevicesFormPacket(IspEnvironment, 'W', AD_PACKET_SIZE, address, prog_data,
&packet);
AnalogDevicesSendPacket(IspEnvironment, &packet);
address += AD_PACKET_SIZE;
prog_data += AD_PACKET_SIZE;
bytes -= AD_PACKET_SIZE;
DebugPrintf(2, ".");
}
if (bytes > 0)
{
AnalogDevicesFormPacket(IspEnvironment, 'W', bytes, address, prog_data, &packet);
AnalogDevicesSendPacket(IspEnvironment, &packet);
DebugPrintf(2, ".");
}
}

/***************************** AnalogDevicesDownload ********************/


/** Perform the download into an Analog Devices micro. As a quick and
* dirty hack against flash relocations at 0x80000
* \return 0 if ok, error code else
* \ToDo: possible to implement the return value instead of calling
* exit() in sub-functions
*/
int AnalogDevicesDownload(ISP_ENVIRONMENT *IspEnvironment)
{
AnalogDevicesSync(IspEnvironment);
AnalogDevicesErase(IspEnvironment);
if (IspEnvironment->BinaryLength > 0x80000)
{
DebugPrintf(2, "Note: Flash remapped 0x80000 to 0.\n");
AnalogDevicesWrite(IspEnvironment, IspEnvironment->BinaryContent + 0x80000, 0,
IspEnvironment->BinaryLength-0x80000);
}
else
{
AnalogDevicesWrite(IspEnvironment, IspEnvironment->BinaryContent, 0, IspEnvironment-
>BinaryLength);
}
return (0);
}
#endif // AD_SUPPORT

Vous aimerez peut-être aussi