source: ISPProgrammer/ISPprog/MemBuffer.pas

Last change on this file was 363, checked in by chronos, 13 years ago
  • Added: Package ISPProgrammer for in-system programming of various chips. Supports Dallas ISP protocol, Presto, Rabbit RFU and some others Atmel devices.
File size: 12.3 KB
Line 
1unit MemBuffer;
2
3{$MODE Delphi}
4
5interface
6
7uses Processors;
8
9const
10 BUF_FLASH = 0;
11 BUF_EEPROM = 1;
12 BUF_USERSIG = 2;
13 FILE_TYPE_INTELHEX = 0;
14 FILE_TYPE_BINARY = 1;
15
16procedure ClearBuffer(bufid:byte);
17function LoadFile(bufid:byte; filetype:integer; fname:string; buflen:integer;
18 var minaddr, maxaddr:integer):string;
19function SaveFile(bufid:byte; filetype:integer; fname:string; buflen:integer):string;
20function LoadIntelHex(bufid:byte; fname:string; buflen:integer;
21 var minaddr, maxaddr:integer):string;
22function SaveIntelHex(bufid:byte; fname:string; buflen:integer):string;
23function LoadBinaryFile(bufid:byte; fname:string; buflen:integer;
24 var minaddr, maxaddr:integer):string;
25function SaveBinaryFile(bufid:byte; fname:string; buflen:integer):string;
26function HighestUsed(bufid:byte; buflen:integer):integer;
27function LowestUsed(bufid:byte; buflen:integer):integer;
28function IsBlockEmpty(bufid:byte; startadr:integer; len:integer):boolean;
29function IsIntelHex(fname:string; bufid:byte):boolean;
30function IsIntelHexFilename(fname:string):boolean;
31
32var
33 flashbuffer:array[0..MAX_FLASH_SIZE-1] of byte;
34 eeprombuffer:array[0..MAX_EEPROM_SIZE-1] of byte;
35 usersigbuffer:array[0..MAX_USERSIG_SIZE-1] of byte;
36
37implementation
38
39uses SysUtils;
40
41procedure ClearBuffer(bufid:byte);
42begin
43 if bufid = BUF_FLASH then
44 FillChar(flashbuffer, sizeof(flashbuffer), $FF)
45 else if bufid = BUF_EEPROM then
46 FillChar(eeprombuffer, sizeof(eeprombuffer), $FF)
47 else if bufid = BUF_USERSIG then
48 FillChar(usersigbuffer, sizeof(usersigbuffer), $FF);
49end;
50
51function LoadFile(bufid:byte; filetype:integer; fname:string; buflen:integer;
52 var minaddr, maxaddr:integer):string;
53begin
54 if filetype = FILE_TYPE_INTELHEX then
55 Result:=LoadIntelHex(bufid, fname, buflen, minaddr, maxaddr)
56 else
57 Result:=LoadBinaryFile(bufid, fname, buflen, minaddr, maxaddr);
58end;
59
60function SaveFile(bufid:byte; filetype:integer; fname:string; buflen:integer):string;
61begin
62 if filetype = FILE_TYPE_INTELHEX then
63 Result:=SaveIntelHex(bufid, fname, buflen)
64 else
65 Result:=SaveBinaryFile(bufid, fname, buflen);
66end;
67
68function LoadIntelHex(bufid:byte; fname:string; buflen:integer;
69 var minaddr, maxaddr:integer):string;
70var
71 line:string;
72 radr,segadr,aktline,code,p_cr,p_lf:integer;
73 b,rlen,rtyp,x,n:byte;
74 f:textfile;
75begin
76 if buflen = 0 then
77 begin
78 Result:='Can''t load file';
79 Exit;
80 end;
81 AssignFile(f, fname);
82 {$I-} Reset(f); {$I+}
83 if IOResult <> 0 then
84 begin
85 Result:='Can''t open file '+fname;
86 Exit;
87 end;
88 minaddr:=High(integer);
89 maxaddr:=Low(integer);
90 segadr:=0;
91 aktline:=0;
92 rtyp:=1;
93 repeat
94 Readln(f, line);
95 repeat
96 Inc(aktline);
97 if (line <> '') then
98 begin
99 if (line[1] <> ':') then
100 begin
101 CloseFile(f);
102 Result:='Error in file '+fname+', line '+IntToStr(aktline);
103 Exit;
104 end;
105 Val('$' + Copy(line, 2, 2), rlen, code);
106 if code <> 0 then
107 begin
108 CloseFile(f);
109 Result:='Error in file '+fname+', line '+IntToStr(aktline);
110 Exit;
111 end;
112 Val('$' + Copy(line, 4, 4), radr, code);
113 if code <> 0 then
114 begin
115 CloseFile(f);
116 Result:='Error in file '+fname+', line '+IntToStr(aktline);
117 Exit;
118 end;
119 Val('$' + Copy(line, 8, 2), rtyp, code);
120 if code <> 0 then
121 begin
122 CloseFile(f);
123 Result:='Error in file '+fname+', line '+IntToStr(aktline);
124 Exit;
125 end;
126 if rtyp = 2 then
127 begin
128 // Extended Segment Address Record
129 Val('$' + Copy(line, 10, 2), b, code);
130 if code <> 0 then
131 begin
132 CloseFile(f);
133 Result:='Error in file '+fname+', line '+IntToStr(aktline);
134 Exit;
135 end;
136 segadr:=longword(b) shl 12;
137 Val('$' + Copy(line, 12, 2), b, code);
138 if code <> 0 then
139 begin
140 CloseFile(f);
141 Result:='Error in file '+fname+', line '+IntToStr(aktline);
142 Exit;
143 end;
144 segadr:=longword(segadr) + (longword(b) shl 4);
145 end
146 else if rtyp = 4 then
147 begin
148 // Extended Linear Address Record
149 Val('$' + Copy(line, 10, 2), b, code);
150 if code <> 0 then
151 begin
152 CloseFile(f);
153 Result:='Error in file '+fname+', line '+IntToStr(aktline);
154 Exit;
155 end;
156 segadr:=longword(b) shl 24;
157 Val('$' + Copy(line, 12, 2), b, code);
158 if code <> 0 then
159 begin
160 CloseFile(f);
161 Result:='Error in file '+fname+', line '+IntToStr(aktline);
162 Exit;
163 end;
164 segadr:=longword(segadr) + (longword(b) shl 16);
165 end
166 else if rtyp = 0 then
167 begin
168 // Data Record
169 radr:=radr + segadr; // add Extended Segment Address
170 x:=10;
171 for n:=1 to rlen do
172 begin
173 Val('$' + Copy(line, x, 2), b, code);
174 if code <> 0 then
175 begin
176 CloseFile(f);
177 Result:='Error in file '+fname+', line '+IntToStr(aktline);
178 Exit;
179 end;
180 if radr < buflen then
181 begin
182 if bufid = BUF_FLASH then
183 flashbuffer[radr]:=b
184 else if bufid = BUF_EEPROM then
185 eeprombuffer[radr]:=b
186 else if bufid = BUF_USERSIG then
187 usersigbuffer[radr]:=b;
188 // search lowest used address
189 if (minaddr > radr) then
190 minaddr:=radr;
191 // search highest used address
192 if (maxaddr < radr) then
193 maxaddr:=radr;
194 end;
195 Inc(x, 2);
196 Inc(radr);
197 end;
198 end;
199 end;
200 p_cr:=Pos(#13, line);
201 if p_cr <> 0 then
202 Delete(line, 1, p_cr);
203 p_lf:=Pos(#10, line);
204 if p_lf <> 0 then
205 Delete(line, 1, p_lf);
206 until (line='') or ((p_cr=0) and (p_lf=0));
207 until (rtyp=1) or Eof(f);
208 CloseFile(f);
209 Result:='';
210end;
211
212function SaveIntelHex(bufid:byte; fname:string; buflen:integer):string;
213var
214 line:string;
215 f:textfile;
216 radr,d1:integer;
217 b,n,rsum,rlen:byte;
218 use_segaddr,use_linaddr:boolean;
219begin
220 if buflen = 0 then
221 begin
222 Result:='Can''t save file';
223 Exit;
224 end;
225 AssignFile(f, fname);
226 {$I-} Rewrite(f); {$I+}
227 if IOResult <> 0 then
228 begin
229 Result:='Can''t create file ' + fname;
230 Exit;
231 end;
232 use_segaddr:=(buflen > 65536) and (buflen <= 1048576);
233 use_linaddr:=(buflen > 1048576);
234 radr:=0;
235 d1:=buflen;
236 repeat
237 if (radr > 0) and ((radr and $ffff) = 0) then
238 begin
239 if (use_segaddr) then
240 begin
241 // Extended Segment Address Record (data size over 64 KB and up to 1 MB)
242 rsum:=4 + Hi(word(radr shr 4)) + Lo(word(radr shr 4));
243 line:=':02000002' + IntToHex(radr shr 4, 4) + IntToHex(byte(0 - rsum), 2);
244 Writeln(f, line);
245 end
246 else
247 if (use_linaddr) then
248 begin
249 // Extended Linear Address Record (data size over 1 MB)
250 rsum:=6 + Hi(word(radr shr 16)) + Lo(word(radr shr 16));
251 line:=':02000004' + IntToHex(radr shr 16, 4) + IntToHex(byte(0 - rsum), 2);
252 Writeln(f, line);
253 end;
254 end;
255 if d1 > 16 then
256 rlen:=16
257 else
258 rlen:=d1;
259 line:=':' + IntToHex(rlen, 2) + IntToHex(radr and $ffff, 4) + '00';
260 rsum:=rlen + Hi(word(radr)) + Lo(word(radr));
261 for n:=0 to rlen - 1 do
262 begin
263 if bufid = BUF_FLASH then
264 b:=flashbuffer[radr]
265 else if bufid = BUF_EEPROM then
266 b:=eeprombuffer[radr]
267 else if bufid = BUF_USERSIG then
268 b:=usersigbuffer[radr]
269 else
270 b:=$ff;
271 line:=line + IntToHex(b, 2);
272 rsum:=rsum + b;
273 Inc(radr);
274 Dec(d1);
275 end;
276 line:=line + IntToHex(byte(0 - rsum), 2);
277 Writeln(f, line);
278 until d1 = 0;
279 Writeln(f, ':00000001FF');
280 CloseFile(f);
281 Result:='';
282end;
283
284function LoadBinaryFile(bufid:byte; fname:string; buflen:integer;
285 var minaddr, maxaddr:integer):string;
286var
287 f:file;
288const
289 numrd:integer = 0;
290begin
291 if buflen = 0 then
292 begin
293 Result:='Can''t load file';
294 Exit;
295 end;
296 AssignFile(f, fname);
297 {$I-} Reset(f, 1); {$I+}
298 if IOResult <> 0 then
299 begin
300 Result:='Can''t open file ' + fname;
301 Exit;
302 end;
303 minaddr:=0;
304 if bufid = BUF_FLASH then
305 BlockRead(f, flashbuffer, buflen, numrd)
306 else if bufid = BUF_EEPROM then
307 BlockRead(f, eeprombuffer, buflen, numrd)
308 else if bufid = BUF_USERSIG then
309 BlockRead(f, usersigbuffer, buflen, numrd);
310 CloseFile(f);
311 if numrd <= 0 then
312 begin
313 Result:='File ' + fname + ' is empty';
314 Exit;
315 end;
316 maxaddr:=numrd - 1;
317 Result:='';
318end;
319
320function SaveBinaryFile(bufid:byte; fname:string; buflen:integer):string;
321var
322 f:file;
323const
324 numwr:integer = 0;
325begin
326 if buflen = 0 then
327 begin
328 Result:='Can''t save file';
329 Exit;
330 end;
331 AssignFile(f, fname);
332 {$I-} Rewrite(f, 1); {$I+}
333 if IOResult <> 0 then
334 begin
335 Result:='Can''t create file ' + fname;
336 Exit;
337 end;
338 if bufid = BUF_FLASH then
339 BlockWrite(f, flashbuffer, buflen, numwr)
340 else if bufid = BUF_EEPROM then
341 BlockWrite(f, eeprombuffer, buflen, numwr)
342 else if bufid = BUF_USERSIG then
343 BlockWrite(f, usersigbuffer, buflen, numwr);
344 CloseFile(f);
345 if numwr <> buflen then
346 begin
347 Result:='Can''t write file ' + fname;
348 Exit;
349 end;
350 Result:='';
351end;
352
353function HighestUsed(bufid:byte; buflen:integer):integer;
354var i:integer;
355begin
356 if bufid = BUF_FLASH then
357 begin
358 for i:=buflen - 1 downto 0 do
359 if flashbuffer[i] <> $ff then
360 begin
361 Result:=i;
362 Exit;
363 end;
364 Result:=-1;
365 end
366 else if bufid = BUF_EEPROM then
367 begin
368 for i:=buflen - 1 downto 0 do
369 if eeprombuffer[i] <> $ff then
370 begin
371 Result:=i;
372 Exit;
373 end;
374 Result:=-1;
375 end
376 else if bufid = BUF_USERSIG then
377 begin
378 for i:=buflen - 1 downto 0 do
379 if usersigbuffer[i] <> $ff then
380 begin
381 Result:=i;
382 Exit;
383 end;
384 Result:=-1;
385 end
386 else
387 Result:=-1;
388end;
389
390function LowestUsed(bufid:byte; buflen:integer):integer;
391var i:integer;
392begin
393 if bufid = BUF_FLASH then
394 begin
395 for i:=0 to buflen - 1 do
396 if flashbuffer[i] <> $ff then
397 begin
398 Result:=i;
399 Exit;
400 end;
401 Result:=-1;
402 end
403 else if bufid = BUF_EEPROM then
404 begin
405 for i:=0 to buflen - 1 do
406 if eeprombuffer[i] <> $ff then
407 begin
408 Result:=i;
409 Exit;
410 end;
411 Result:=-1;
412 end
413 else if bufid = BUF_USERSIG then
414 begin
415 for i:=0 to buflen - 1 do
416 if usersigbuffer[i] <> $ff then
417 begin
418 Result:=i;
419 Exit;
420 end;
421 Result:=-1;
422 end
423 else
424 Result:=-1;
425end;
426
427function IsBlockEmpty(bufid:byte; startadr:integer; len:integer):boolean;
428var i:integer;
429begin
430 Result:=false;
431 if bufid = BUF_FLASH then
432 begin
433 for i:=startadr to startadr + len - 1 do
434 if flashbuffer[i] <> $ff then
435 Exit;
436 end
437 else if bufid = BUF_EEPROM then
438 begin
439 for i:=startadr to startadr + len - 1 do
440 if eeprombuffer[i] <> $ff then
441 Exit;
442 end
443 else if bufid = BUF_USERSIG then
444 begin
445 for i:=startadr to startadr + len - 1 do
446 if usersigbuffer[i] <> $ff then
447 Exit;
448 end;
449 Result:=true;
450end;
451
452function IsIntelHex(fname:string; bufid:byte):boolean;
453var buflen, minaddr, maxaddr:integer;
454begin
455 Result:=false;
456 if bufid = BUF_FLASH then
457 buflen:=MAX_FLASH_SIZE
458 else if bufid = BUF_EEPROM then
459 buflen:=MAX_EEPROM_SIZE
460 else if bufid = BUF_USERSIG then
461 buflen:=MAX_USERSIG_SIZE
462 else
463 Exit;
464 maxaddr:=0; minaddr:=0;
465 if LoadIntelHex(bufid, fname, buflen, minaddr, maxaddr) = '' then
466 Result:=true;
467end;
468
469function IsIntelHexFilename(fname:string):boolean;
470var ext:string;
471begin
472 ext:=LowerCase(ExtractFileExt(fname));
473 Result:=((ext = 'hex') or (ext = 'eep') or (ext = 'rom') or (ext = 'ihx'));
474end;
475
476end.
Note: See TracBrowser for help on using the repository browser.