home *** CD-ROM | disk | FTP | other *** search
- #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);
-
- }
-