where : ibrtses delphi

Delphi - Intel Hex

disclaimer

the source code of this page may not appear correctly in certain browsers
due to special characters. Have a look at the source of this HTML page
with notepad instead

format

Intel Hex is a common format to store binaries to be loaded into EPROM for
CPU's. It is a readable textformat that is line oriented. A line is built as

':', rec len, address, rec type, [data], checksum
whereas :
':' is start of record = 0x3A
reclen is the number of databytes as 2 digit hex
address is 4 digit hex, where the data starts
rec type is '00' for normal data, '01' end of file, '02' extended adress
[data] is a data packet encoded as hex
checksum is the 2's complement of the sum over the record excl the ':' modulo 256 as hex

eg :
:1005AA00000102030405060708090A0B0C0D0E0F88
rec len = 0x10 = 16
address = 0x05AA
data = 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
checksum = 0x88 = 256 -sum(0x00+..+0x0F)= 256- 0x78

reading a line

it assumes a buffer big enough to store the data :
type mybuf=array[0..??]of byte;
var Buf:mybuf;
function readline(s:string; var Buf:mybuf):integer; // returns error code 0=ok
var ladr:integer;
 csum,ndb,rtyp,data:byte;
 t:shortstring;
begin
 if s[1]=':' then begin
  t:='$'+copy(s,2,2);         // get length
  ndb:=strtoint(t);
  {$R-}csum:=csum+rl;{$R+}
  t:='$'+copy(ss,4,4);        // get address
  ladr:=strtoint(t);
  {$R-}csum:=csum+lo(ladr)+hi(ladr);{$R+}
  t:='$'+copy(ss,8,2);
  rtyp:=strtoint(t);
  {$R-}csum:=csum+rtyp;{$R+}
  case rtyp of
   0:begin    			// datablock
     bcount:=0;
     while (bcount < ndb) do begin
      t:='$'+copy(ss,10+2*bcount,2);
      data:=strtoint(t);
      {$R-}csum:=csum+data;{$R+}
      Buf[ladr+bcount]:=data;
      inc(bcount);
     end;
     t:='$'+copy(ss,10+2*bcount,2);
     css:=strtoint(t);
     end;
   1:begin			// end of file
      t:='$'+copy(ss,10,2);
      css:=strtoint(t);
      result:=1;
     end;
   2:begin      	// extended segment address
      ...
     end;
   3:begin     		// start address record
      ...
     end;
   4:begin
      ...
     end;
   5:begin
      ...
     end;
     else result = -2;  // no valid record
    end; //case
  // test checksum
  {$R-}data:=css+csum;{$R+}
  if (data<>0) then result:=-2; // checksum error
 end
 else result:=-0; // no record
end;

Writing a line

function writeline(adr,len:integer; var buf:mybuf):shortstring;
var i:integer;
 csum:byte;
begin
 csum:=0;
 result:=':'+inttohex(len,2)+inttohex(adr,4);
 {$R-} csum:=len+lo(adr)+hi(adr);{$R+}
 for i:=0 to len-1 do begin
  result:=result+inttohex(buf[adr+i],2);
  {$R-}csum:=csum+buf[adr+i];{$R+}
 end;
 result:=result+inttohex(-csum,2);
end;

function write_eof(startadr:integer):shortstring;
var csum:byte;
begin
 result:=':00'+inttohex(startadr,4)+'01';
 csum:=hi(startadr)+lo(startadr)+1;
 result:=inttohex(-csum,2);
end;

Use

use them as :
 reading

 memo1.lines.loadfromfile('myhex_file.hex');
 i:=0; 
 res:=0;
 stop:=false;
 while (i <= memo1.lines.count-1)and(not stop) do begin
  res:=readline(memo1.line[i],buf);
  stop:=(res=1);    // stop on end of file
 end;

 writing

 memo1.clear;
 adr:=0;
 for i:=0 to ((usedbuf-1) div 16) do begin
  memo1.lines.add(writeline(adr,16,mybuf));
  adr:=adr+16;
 end;
 if (usedbuf>adr) then 
  memo1.lines.add(writeline(adr,(usedbuf mod 16),mybuf));
 memo1.lines.add(write_eof(0));

notes

There are extended formats, and there is the chance that the EPROM
is not located at 0x0000, but at 0xF0000 or similar. A further
search on the web may reveal enhancements or solutions to other
problems.



Feedback is welcome





sponsored links




Delphi
home

last updated: 4.jan.00

Copyright (99,2000) Ing.Büro R.Tschaggelar