home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
datafiles
/
hardware
/
eprommer
/
source.lha
/
src
/
intelhex.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-26
|
7KB
|
285 lines
#define _INTELHEX
#define MIN(a,b) (((a>b)?b:a))
#define MAX(a,b) (((a<b)?b:a))
#include "intelhex.h"
/*#define DEBUG*/
#ifdef DEBUG
extern FILE *fpdebug;
#endif
void mystrncpy(char *dest,char *src,int n)
{
/* Like the normal 'strncpy()' but appends a '\0' at end */
while(n--)
*dest++=*src++;
*dest='\0';
}
char *readintelhex(FILE *fp,unsigned char *buffer,int maxbuffer,long *plength,int flag,long *p_epromstart)
{
/* Read a file in 'intelhex'-Format. Decode the data, check the
* Checksum, fill the buffer with data.
* IF 'flag'==CONTINOUS no fragmented data is allowed,
* plength is set to real read number of bytes
* IF 'flag'==FRAGMENTED plength is set to size of part of used buffer
*
* RC: NULL if all went fine, else
* Pointer to an error Message
*/
char line[BUFSIZ], /* ASCII Buffer for reading line */
tmpbuf[5], /* Buffer to extract and convert hex numbers */
*dummy; /* like the name */
static char errormsg[256]; /* buffer for Error Message */
int ndata, /* number of Databytes */
data, /* one databyte */
address, /* address for data */
status, /* status of intelhex line */
chksum, /* checksum of intelhex line */
sum, /* own calculated checksum */
lnr=0, /* linenumber */
totalbytes=0, /* total bytes written to buffer */
highaddr, /* determine the highest used buffer address */
lowaddr, /* determine the lowest used buffer address */
i;
/* temp. Pointer to Binary Databuffer */
unsigned char *pbuf=(unsigned char *)-1;
#ifdef DEBUG
fprintf(fpdebug,"readintelhex()\n");
#endif
/* set to ERROR */
*plength=0;
while(fgets(line,BUFSIZ,fp))
{
lnr++;
#ifdef DEBUG
fprintf(fpdebug,"readih: line:%d\n",lnr);
#endif
if(line[IH_COLON]!=':')
{
if(lnr==1) /* First line ? */
sprintf(errormsg,"No IntelHex Format");
else
sprintf(errormsg,"Line:%d Expected ':' at first character, get '%c'\nIs the File in IntelHex Format ?\n",lnr,line[IH_COLON]);
return(errormsg);
}
/* get number of databytes */
mystrncpy(tmpbuf,&line[IH_NRDATA],2);
ndata = strtol(tmpbuf,&dummy,16);
/* get address */
mystrncpy(tmpbuf,&line[IH_ADDRESS],4);
address = strtol(tmpbuf,&dummy,16);
/* note used buffer range */
if(lnr==1)
{ /* Initialize */
highaddr=address+ndata-1;
lowaddr=address;
}
else
{
lowaddr = MIN(lowaddr,address);
highaddr= MAX(highaddr,address+ndata-1);
}
/*printf("lnr:%d, addr:%x low:%x high:%x ndata=%d\n",lnr,address,lowaddr,highaddr,ndata);*/
/* get status */
mystrncpy(tmpbuf,&line[IH_STATUS],2);
status = strtol(tmpbuf,&dummy,16);
/* get chksum */
mystrncpy(tmpbuf,&line[IH_FIRSTDATA+2*ndata],2);
chksum = strtol(tmpbuf,&dummy,16);
/* build first part of own checksum */
sum = ndata + (0xFF&(address>>8)) + (0xFF&address) + status;
/* check if last intelhex line */
if(ndata==0)
{
#ifdef DEBUG
printf("ndata=%d status=%d chksum=%d totalbytes=%d\n",ndata,status,chksum,totalbytes);
#endif
if( (status!=1) || (chksum!=0xFF))
{
sprintf(errormsg,"Line:%d ndata=0 but status=%d\n",lnr,status);
return(errormsg);
}
else
{
/* set total written bytes */
/*printf("end: total:%d calc:%d\n",totalbytes,highaddr-lowaddr+1);*/
*plength = (flag==CONTINOUS) ? totalbytes : highaddr-lowaddr+1 ;
*p_epromstart = lowaddr;
return(NULL);
}
}
/* check if is status correct */
if(status!=0)
{
sprintf(errormsg,"Line:%d Wrong status, expected 0 not %d",lnr,status);
return(errormsg);
}
/* check if is internal buffer big enough */
if(address+ndata>maxbuffer)
{
sprintf(errormsg,"Line:%d Too much data, internal Buffer max:%d\n",lnr,maxbuffer);
return(errormsg);
}
if(pbuf!=(unsigned char *)-1)
{
if( (flag==CONTINOUS) && (pbuf!=buffer + address) )
{
sprintf(errormsg,"Line:%d Data not continous",lnr);
return(errormsg);
}
}
i=IH_FIRSTDATA; /* first databyte in intelhex line */
pbuf = buffer + address; /* first buffer position */
while(ndata--)
{
mystrncpy(tmpbuf,&line[i],2);
data = strtol(tmpbuf,&dummy,16);
*pbuf++=(unsigned char)data;
i+=2;
sum+=data;
totalbytes++;
}
/* make chksum complete */
sum = 0xFF & ( 0x100 - sum );
/* compare checksum's */
if(chksum != sum)
{
sprintf(errormsg,"Line:%d Checksum differs, read:%d calculate:%d\n",lnr,chksum,sum);
return(errormsg);
}
}
if(feof(fp))
{
sprintf(errormsg,"Line:%d No END Status found",lnr);
return(errormsg);
}
sprintf(errormsg,"Line:%d Error reading File",lnr);
return(errormsg);
}
char *itoh(unsigned char byte,char *pbuf)
{
/* Convert 'byte' in ASCII Hex Notation.
*
* Write ASCII Hex Code (2 Chars) at '*pbuf'.
*
* RC: pbuf+2 (points to next free char
*/
unsigned char low, /* low 4 Bits of 'byte' */
high; /* high 4 Bits of 'byte' (normalized) */
low = 0x0F&byte;
/* high = (unsigned char)(((int)(0xF0&byte))>>4);*/
high = (unsigned char)(0xF0&byte)>>4;
/* convert Integer to ASCII Hex */
*pbuf++= (high<=9) ? high+'0' : (high-0x0A)+'A';
*pbuf++= (low<=9) ? low+'0' : (low-0x0A)+'A';
return(pbuf);
}
char *writeintelhex(FILE *fp,unsigned char *buffer,int offset,int length)
{
/* Write a file in 'intelhex'-Format.
* Code the binary data:
* Determine Address, calculate checksum, write intelhex line.
*
* RC: NULL if all went fine, else
* Pointer to an error Message
*/
char line[BUFSIZ], /* ASCII Buffer for writing line */
*pos; /* used for filling intelhex line */
static char errormsg[256]; /* buffer for Error Message */
int ndata, /* number of Databytes */
data, /* one databyte */
address, /* address for data */
status, /* status of intelhex line */
chksum, /* checksum of intelhex line */
lnr=0; /* linenumber */
address=offset; /* set logically startaddress */
status=0; /* set status */
line[IH_COLON]=':'; /* set Start Marker */
while(length)
{
lnr++; /* linenumber counting */
/* write maximal IH_MAXDATA to one intelhex line */
ndata=MIN(IH_MAXDATA,length);
/* remaining data */
length-=ndata;
/* build first part of checksum */
chksum = ndata + (0xFF&(address>>8)) + (0xFF&address) + status;
pos = &line[1]; /* points to second byte of line */
pos = itoh((unsigned char)ndata,pos); /* Write data counter */
pos = itoh((unsigned char)(address>>8),pos); /* Write High Byte Address */
pos = itoh((unsigned char)(0xFF&address),pos); /* Write Low Byte Address */
pos = itoh((unsigned char)status,pos); /* Write status */
/* calculate address for next line */
address+=ndata;
while(ndata--)
{
data=*buffer;
buffer++;
chksum+=data; /* adding for chksum */
pos = itoh((unsigned char)data,pos); /* Write databyte */
}
chksum=0xFF&(0x100-(0xFF&chksum));
pos = itoh(chksum,pos); /* Write chksum */
*pos++ = '\n'; /* Close String */
*pos = '\0'; /* Close String */
if(fputs(line,fp)<0)
{
sprintf(errormsg,"Line:%d Can't write line",lnr);
return(errormsg);
}
}
fputs(":00000001FF\n",fp);
return(NULL);
}