/*
* dspicdmp.c -- utility for dumping the contents of a dsPIC
* -- chip to a COFF file using a jdm-style serial
* -- port programmer
*
* homer reid -- 1/2005
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <ctype.h>
#include "dspicprg.h"
/***************************************************/
/* Usage message ***********************************/
/***************************************************/
char *Usage=
"\nusage: dspicdmp [options]\n\n"
" Options:\n"
" -c xx, --chip=xx specify dsPIC model [pic30f2010]\n"
" -f xx, --hexfile=xx specify name of output file[dspicdmp.hex]\n"
" -h, --help print this message\n"
" -p xx, --portbase=xx specify serial port base [0x3F8]\n\n";
/***************************************************/
/* Process command-line arguments. *****************/
/***************************************************/
struct option Options[] =
{ { "chip", 1, 0, 'c' },
{ "hexfile", 1, 0, 'f' },
{ "help", 0, 0, 'h' },
{ "portbase", 1, 0, 'p' },
{ 0,0,0,0 }
};
void ProcessOptions(int argc, char *argv[])
{ int i;
char c, buffer[100];
char *HexFileName="dspicdmp.hex";
while((c=getopt_long(argc, argv, "c:f:p:h", Options, 0)))
{
if (c==-1)
break;
switch(c)
{
/* look for chip in list of supported chips */
case 'c':
WhichChip=0;
for (i=0; SupportedChips[i].Name!=0; i++)
if ( !strcasecmp(optarg,SupportedChips[i].Name) )
{ WhichChip=&(SupportedChips[i]);
break;
};
if (!WhichChip)
{ fprintf(stderr,"unknown chip specification %s\n",optarg);
fprintf(stderr," supported chips: \n");
for (i=0; SupportedChips[i].Name!=0; i++)
fprintf(stderr," %s\n",SupportedChips[i].Name);
exit(1);
};
break;
case 'f':
HexFileName=optarg;
break;
case 'p':
PortBase=atoi(optarg);
if ( PortBase<=0 || PortBase >= 0x400 )
ErrExit("invalid port base %X",PortBase);
break;
case 'h':
default:
printf(Usage);
exit(1);
}; /* switch(c); */
}; /* while (c= ... ) */
/*
* Try to open output file.
*/
if ((HexFile=fopen(HexFileName,"r")))
{ fclose(HexFile);
fprintf(stderr,"File %s exists; overwrite (y/n)? ",HexFileName);
fgets(buffer,100,stdin);
if ( tolower(buffer[0]) !='y' ) exit(1);
};
if ( !(HexFile=fopen(HexFileName,"w")) )
ErrExit("could not open file %s for writing",HexFileName);
}
/***************************************************/
/* main routine ************************************/
/***************************************************/
int main(int argc, char *argv[])
{
DWORD Address, AddressHigh, MaxAddress;
BYTE UBuf[16],PBuf[12];
/*
* Process command-line options.
*/
ProcessOptions(argc,argv);
/*
* Initialize hardware and enter STDP mode.
*/
HWInit();
EnterSTDPMode();
/*
* Read all of code memory, 4 program words
* (12 bytes) at a time, and write to hex file.
*/
bzero(UBuf,16);
AddressHigh=0;
WriteELARecord(0);
MaxAddress=2*WhichChip->ProgramWords;
for (Address=0; Address<MaxAddress; Address+=8)
{
/*
* emit an ELA record to the hex file whenever
* the upper word of the address increments
*/
if ( (Address&0xFFFF0000) != AddressHigh )
{ AddressHigh=Address&0xFFFF0000;
WriteELARecord( Address );
};
STDPSeq(STDP_READCODE,Address,PBuf,0);
CodeUnpack(PBuf,UBuf); /* unpack weird byte ordering */
WriteDataRecord(Address&0xFFFF,UBuf);
};
/*
* Read all of data eeprom and write to hex file.
* Note that the pic30-hex file format stores
* each two-byte data word as a four-byte dword
* (with upper two msbs both zero).
*/
bzero(UBuf,16);
/* the upper word of the address for data eeprom */
/* is always 0x007F for all dsPIC devices */
WriteELARecord(0x007F0000);
MaxAddress=0x10000;
Address=MaxAddress - 2*WhichChip->DataWords;
for ( ; Address<MaxAddress; Address+=8)
{
STDPSeq(STDP_READDATA,Address,PBuf,0);
DataUnpack(PBuf,UBuf);
WriteDataRecord(Address&0xFFFF,UBuf);
};
/*
* Read configuration memory and write to hex
* file.
*/
WriteELARecord(0x00F80000);
STDPSeq(STDP_READCFG,0,PBuf,0);
DataUnpack(PBuf,UBuf);
WriteDataRecord(0,UBuf);
DataUnpack(PBuf+8,UBuf);
WriteDataRecord(8,UBuf);
WriteEOFRecord();
ExitSTDPMode();
fclose(HexFile);
printf("Thank you for your support.\n");
return 0;
}