Refs #226. Refactored the TFirmwareData class such that it can be used in Lazarus as well.

git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@200 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
Frank Voorburg 2017-01-05 12:10:35 +00:00
parent f7f8c387ba
commit d312562e40
1 changed files with 148 additions and 17 deletions

View File

@ -29,6 +29,10 @@ unit FirmwareData;
// should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. // should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
// //
//*************************************************************************************** //***************************************************************************************
{$IFDEF FPC}
{$mode objfpc}
{$ENDIF}
interface interface
@ -36,7 +40,7 @@ interface
// Includes // Includes
//*************************************************************************************** //***************************************************************************************
uses uses
Windows, Messages, SysUtils, Classes, Math, Generics.Collections, Generics.Defaults; SysUtils, Classes;
//*************************************************************************************** //***************************************************************************************
@ -69,6 +73,21 @@ type
property LastAddress: Longword read GetLastAddress; property LastAddress: Longword read GetLastAddress;
end; end;
//---------------------------------- TDataSegmentList ---------------------------------
TDataSegmentList=class(TList)
private
function Get(Index: Integer): TDataSegment;
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create;
destructor Destroy; override;
function Add(segment: TDataSegment): Integer;
procedure Delete(Index: Integer);
property Items[Index: Integer]: TDataSegment read Get; default;
end;
//---------------------------------- TFirmwareFileType -------------------------------- //---------------------------------- TFirmwareFileType --------------------------------
TFirmwareFileType = TFirmwareFileType =
( (
@ -88,7 +107,7 @@ type
public public
constructor Create; virtual; constructor Create; virtual;
function Load(firmwareFile: String): Boolean; virtual; abstract; function Load(firmwareFile: String): Boolean; virtual; abstract;
function Save(firmwareFile: String; segments: TObjectList<TDataSegment>): Boolean; virtual; abstract; function Save(firmwareFile: String; segments: TDataSegmentList): Boolean; virtual; abstract;
property OnDataRead: TFirmwareFileDataReadEvent read FOnDataRead write FOnDataRead; property OnDataRead: TFirmwareFileDataReadEvent read FOnDataRead write FOnDataRead;
end; end;
@ -104,7 +123,7 @@ type
public public
constructor Create; override; constructor Create; override;
function Load(firmwareFile: String): Boolean; override; function Load(firmwareFile: String): Boolean; override;
function Save(firmwareFile: String; segments: TObjectList<TDataSegment>): Boolean; override; function Save(firmwareFile: String; segments: TDataSegmentList): Boolean; override;
class function IsSRecordFile(firmwareFile: String): Boolean; static; class function IsSRecordFile(firmwareFile: String): Boolean; static;
property DataBytesPerLineOnSave: Integer read FDataBytesPerLineOnSave write FDataBytesPerLineOnSave; property DataBytesPerLineOnSave: Integer read FDataBytesPerLineOnSave write FDataBytesPerLineOnSave;
end; end;
@ -115,14 +134,14 @@ type
public public
constructor Create; override; constructor Create; override;
function Load(firmwareFile: String): Boolean; override; function Load(firmwareFile: String): Boolean; override;
function Save(firmwareFile: String; segments: TObjectList<TDataSegment>): Boolean; override; function Save(firmwareFile: String; segments: TDataSegmentList): Boolean; override;
end; end;
//---------------------------------- TFirmwareData ------------------------------------ //---------------------------------- TFirmwareData ------------------------------------
TFirmwareData = class(TObject) TFirmwareData = class(TObject)
private private
// list with data segments of the firmware // list with data segments of the firmware
FSegmentList: TObjectList<TDataSegment>; FSegmentList: TDataSegmentList;
function GetSegmentCount: Integer; function GetSegmentCount: Integer;
function GetSegment(index: Integer): TDataSegment; function GetSegment(index: Integer): TDataSegment;
procedure SortSegments; procedure SortSegments;
@ -469,9 +488,11 @@ end; //*** end of Remove ***
// //
//*************************************************************************************** //***************************************************************************************
procedure TDataSegment.Dump; procedure TDataSegment.Dump;
{$IFDEF DEBUG}
var var
line: String; line: String;
byteCnt: Integer; byteCnt: Integer;
{$ENDIF}
begin begin
{$IFDEF DEBUG} {$IFDEF DEBUG}
// output address and size // output address and size
@ -494,6 +515,98 @@ begin
end; //*** end of Dump end; //*** end of Dump
//---------------------------------------------------------------------------------------
//-------------------------------- TDataSegmentList -------------------------------------
//---------------------------------------------------------------------------------------
//***************************************************************************************
// NAME: Create
// PARAMETER: none
// RETURN VALUE: none
// DESCRIPTION: Object constructor. Calls TObject's constructor and initializes
// the private property variables to their default values.
//
//***************************************************************************************
constructor TDataSegmentList.Create;
begin
// call inherited constructor
inherited Create;
end; //*** end of Create ***
//***************************************************************************************
// NAME: Destroy
// PARAMETER: none
// RETURN VALUE: none
// DESCRIPTION: Component destructor.
//
//***************************************************************************************
destructor TDataSegmentList.Destroy;
var
idx: Integer;
begin
// release allocated heap memory
for idx := 0 to Count - 1 do
TDataSegment(Items[idx]).Free;
inherited;
end; //*** end of Destroy ***
//***************************************************************************************
// NAME: Get
// PARAMETER: Index Index in the list
// RETURN VALUE: List item.
// DESCRIPTION: Obtains an element from the list.
//
//***************************************************************************************
function TDataSegmentList.Get(Index: Integer): TDataSegment;
begin
Result := TDataSegment(inherited Get(Index));
end; //*** end of Get ***
//***************************************************************************************
// NAME: Add
// PARAMETER: segment The data segment to add.
// RETURN VALUE: Index of the newly added segment in the list if successful, -1
// otherwise.
// DESCRIPTION: Adds an element to the list.
//
//***************************************************************************************
function TDataSegmentList.Add(segment: TDataSegment): Integer;
begin
// add the entry to the list
Result := inherited Add(segment);
// set correct value for error situation
if Result < 0 then
Result := -1;
end; //*** end of Add ***
//***************************************************************************************
// NAME: Delete
// PARAMETER: Index Index in the list.
// RETURN VALUE: none
// DESCRIPTION: Remove an element to the list as the specified index. It is automa-
// tically freed as well.
//
//***************************************************************************************
procedure TDataSegmentList.Delete(Index: Integer);
var
segment: TDataSegment;
begin
// only continue if the index is valid
if (Index >= 0) and (Index < Count) then
begin
// obtain object first so we can free it afterwards
segment := Get(Index);
// delete it from the list
inherited Delete(Index);
// now free it
segment.Free
end;
end; //*** end of Delete ***
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------
//-------------------------------- TFirmwareFileHandler --------------------------------- //-------------------------------- TFirmwareFileHandler ---------------------------------
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------
@ -598,7 +711,7 @@ end; //*** end of Load ***
// DESCRIPTION: Saves the firmware data to the specified firmware file. // DESCRIPTION: Saves the firmware data to the specified firmware file.
// //
//*************************************************************************************** //***************************************************************************************
function TSRecordFileHandler.Save(firmwareFile: String; segments: TObjectList<TDataSegment>): Boolean; function TSRecordFileHandler.Save(firmwareFile: String; segments: TDataSegmentList): Boolean;
var var
srecordFile: TextFile; srecordFile: TextFile;
segmentIdx: Integer; segmentIdx: Integer;
@ -611,6 +724,7 @@ var
headerByteCount: Integer; headerByteCount: Integer;
checksumCalc: Byte; checksumCalc: Byte;
addrByteCnt: Integer; addrByteCnt: Integer;
charIdx: Integer;
begin begin
// init result // init result
Result := True; Result := True;
@ -628,7 +742,9 @@ begin
ReWrite(srecordFile); ReWrite(srecordFile);
// ---- add the S0 header line that contains the filename ---- // ---- add the S0 header line that contains the filename ----
firmwareFileBytes := TEncoding.UTF8.GetBytes(firmwareFile); SetLength(firmwareFileBytes, Length(firmwareFile));
for charIdx := 1 to Length(firmwareFile) do
firmwareFileBytes[charIdx - 1] := Ord(firmwareFile[charIdx]);
headerByteCount := 3 + Length(firmwareFileBytes); headerByteCount := 3 + Length(firmwareFileBytes);
line := 'S0' + Format('%.2X', [headerByteCount]) + '0000'; line := 'S0' + Format('%.2X', [headerByteCount]) + '0000';
for byteIdx := 0 to (Length(firmwareFileBytes) - 1) do for byteIdx := 0 to (Length(firmwareFileBytes) - 1) do
@ -984,7 +1100,7 @@ end; //*** end of Load ***
// DESCRIPTION: Saves the firmware data to the specified firmware file. // DESCRIPTION: Saves the firmware data to the specified firmware file.
// //
//*************************************************************************************** //***************************************************************************************
function TBinaryFileHandler.Save(firmwareFile: String; segments: TObjectList<TDataSegment>): Boolean; function TBinaryFileHandler.Save(firmwareFile: String; segments: TDataSegmentList): Boolean;
var var
startAddr: Longword; startAddr: Longword;
endAddr: Longword; endAddr: Longword;
@ -1064,9 +1180,8 @@ constructor TFirmwareData.Create;
begin begin
// call inherited constructor // call inherited constructor
inherited Create; inherited Create;
// create empty data segments list and set it to own the segments for automatic freeing // create empty data segments list
FSegmentList := TObjectList<TDataSegment>.Create(); FSegmentList := TDataSegmentList.Create();
FSegmentList.OwnsObjects := True;
end; //*** end of Create *** end; //*** end of Create ***
@ -1114,6 +1229,21 @@ begin
end; //*** end of GetSegment *** end; //*** end of GetSegment ***
//***************************************************************************************
// NAME: FirmwareDataCompareSegments
// PARAMETER: Item1 First item for the comparison.
// Item2 Second item for the comparison.
// RETURN VALUE: 1 if Item1's identifier is larger, -1 if Item1's identifier is
// smaller, 0 if the identifiers are equal.
// DESCRIPTION: Custom sorting routine for the entries in filter.
//
//***************************************************************************************
function FirmwareDataCompareSegments(Item1, Item2: Pointer): Integer;
begin
Result := TDataSegment(Item1).BaseAddress - TDataSegment(Item2).BaseAddress;
end; //*** end of FirmwareDataCompareSegments ***
//*************************************************************************************** //***************************************************************************************
// NAME: SortSegments // NAME: SortSegments
// PARAMETER: none // PARAMETER: none
@ -1123,12 +1253,7 @@ end; //*** end of GetSegment ***
//*************************************************************************************** //***************************************************************************************
procedure TFirmwareData.SortSegments; procedure TFirmwareData.SortSegments;
begin begin
FSegmentList.Sort(TComparer<TDataSegment>.Construct( FSegmentList.Sort(@FirmwareDataCompareSegments);
function (const L, R: TDataSegment): integer
begin
result := L.BaseAddress - R.BaseAddress;
end
));
end; //*** end of SortSegments *** end; //*** end of SortSegments ***
@ -1574,7 +1699,11 @@ begin
end; end;
// set onload handler which does the actual data processing // set onload handler which does the actual data processing
{$IFDEF FPC}
firmwareFileHandler.OnDataRead := @FirmwareFileDataRead;
{$ELSE}
firmwareFileHandler.OnDataRead := FirmwareFileDataRead; firmwareFileHandler.OnDataRead := FirmwareFileDataRead;
{$ENDIF}
// load data from the file // load data from the file
Result := firmwareFileHandler.Load(firmwareFile); Result := firmwareFileHandler.Load(firmwareFile);
@ -1631,8 +1760,10 @@ end; //*** end of SaveToFile ***
// //
//*************************************************************************************** //***************************************************************************************
procedure TFirmwareData.Dump; procedure TFirmwareData.Dump;
{$IFDEF DEBUG}
var var
segmentIdx: Integer; segmentIdx: Integer;
{$ENDIF}
begin begin
{$IFDEF DEBUG} {$IFDEF DEBUG}
for segmentIdx := 0 to (SegmentCount - 1) do for segmentIdx := 0 to (SegmentCount - 1) do