library openblt_can_vector; //*************************************************************************************** // Project Name: MicroBoot Interface for Borland Delphi // Description: XCP - CAN interface for MicroBoot supporting Vector CAN // File Name: openblt_can_vector.dpr // //--------------------------------------------------------------------------------------- // C O P Y R I G H T //--------------------------------------------------------------------------------------- // Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved // // This software has been carefully tested, but is not guaranteed for any particular // purpose. The author does not offer any warranties and does not guarantee the accuracy, // adequacy, or completeness of the software and is not responsible for any errors or // omissions or the results obtained from use of the software. // //--------------------------------------------------------------------------------------- // L I C E N S E //--------------------------------------------------------------------------------------- // This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or // modify it under the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) any later // version. // // OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with OpenBLT. // If not, see . // // A special exception to the GPL is included to allow you to distribute a combined work // that includes OpenBLT without being obliged to provide the source code for any // proprietary components. The exception text is included at the bottom of the license // file . // //*************************************************************************************** //*************************************************************************************** // Includes //*************************************************************************************** uses Windows, Messages, Graphics, Controls, Forms, Dialogs, SysUtils, Classes, Extctrls, XcpProtection in '..\..\XcpProtection.pas', SRecReader in '..\..\SRecReader.pas', XcpDataFile in '..\..\XcpDataFile.pas', XcpLoader in '..\..\XcpLoader.pas', XcpTransport in 'XcpTransport.pas', CANdrvD in 'CANdrvD.pas', CANlibD in 'CANlibD.pas', XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}; //*************************************************************************************** // Global Constants //*************************************************************************************** const kMaxProgLen = 256; // maximum number of bytes to progam at one time //*************************************************************************************** // Type Definitions //*************************************************************************************** // DLL Interface Callbacks - modifications requires potential update of all interfaces! type TStartedEvent = procedure(length: Longword) of object; TProgressEvent = procedure(progress: Longword) of object; TDoneEvent = procedure of object; TErrorEvent = procedure(error: ShortString) of object; TLogEvent = procedure(info: ShortString) of object; TInfoEvent = procedure(info: ShortString) of object; type TEventHandlers = class // create a dummy class procedure OnTimeout(Sender: TObject); end; //*************************************************************************************** // Global Variables //*************************************************************************************** var //--- begin of don't change --- AppOnStarted : TStartedEvent; AppOnProgress : TProgressEvent; AppOnDone : TDoneEvent; AppOnError : TErrorEvent; AppOnLog : TLogEvent; AppOnInfo : TInfoEvent; //--- end of don't change --- timer : TTimer; events : TEventHandlers; loader : TXcpLoader; datafile : TXcpDataFile; progdata : array of Byte; progfile : string; stopRequest : boolean; //*************************************************************************************** // NAME: MbiCallbackOnStarted // PARAMETER: length of the file that is being downloaded. // RETURN VALUE: none // DESCRIPTION: Wrapper function for safely calling an application callback // //*************************************************************************************** procedure MbiCallbackOnStarted(length: Longword); begin if Assigned(AppOnStarted) then begin AppOnStarted(length); end; end; //** end of MbiCallbackOnStarted *** //*************************************************************************************** // NAME: MbiCallbackOnProgress // PARAMETER: progress of the file download. // RETURN VALUE: none // DESCRIPTION: Wrapper function for safely calling an application callback // //*************************************************************************************** procedure MbiCallbackOnProgress(progress: Longword); begin if Assigned(AppOnProgress) then begin AppOnProgress(progress); end; end; //** end of MbiCallbackOnProgress *** //*************************************************************************************** // NAME: MbiCallbackOnDone // PARAMETER: none // RETURN VALUE: none // DESCRIPTION: Wrapper function for safely calling an application callback // //*************************************************************************************** procedure MbiCallbackOnDone; begin if Assigned(AppOnDone) then begin AppOnDone; end; end; //** end of MbiCallbackOnDone *** //*************************************************************************************** // NAME: MbiCallbackOnError // PARAMETER: info about the error that occured. // RETURN VALUE: none // DESCRIPTION: Wrapper function for safely calling an application callback // //*************************************************************************************** procedure MbiCallbackOnError(error: ShortString); begin if Assigned(AppOnError) then begin AppOnError(error); end; end; //** end of MbiCallbackOnError *** //*************************************************************************************** // NAME: MbiCallbackOnLog // PARAMETER: info on the log event. // RETURN VALUE: none // DESCRIPTION: Wrapper function for safely calling an application callback // //*************************************************************************************** procedure MbiCallbackOnLog(info: ShortString); begin if Assigned(AppOnLog) then begin AppOnLog(info); end; end; //** end of MbiCallbackOnLog *** //*************************************************************************************** // NAME: MbiCallbackOnInfo // PARAMETER: details on the info event. // RETURN VALUE: none // DESCRIPTION: Wrapper function for safely calling an application callback // //*************************************************************************************** procedure MbiCallbackOnInfo(info: ShortString); begin if Assigned(AppOnInfo) then begin AppOnInfo(info); end; end; //** end of MbiCallbackOnLog *** //*************************************************************************************** // NAME: LogData // PARAMETER: pointer to byte array and the data length // RETURN VALUE: none // DESCRIPTION: Writes the program data formatted to the logfile // //*************************************************************************************** procedure LogData(data : PByteArray; len : longword); stdcall; var currentWriteCnt : byte; cnt : byte; logStr : string; bufferOffset : longword; begin bufferOffset := 0; while len > 0 do begin // set the current write length optimized to log 32 bytes per line currentWriteCnt := len mod 32; if currentWriteCnt = 0 then currentWriteCnt := 32; logStr := ''; // prepare the line to add to the log for cnt := 0 to currentWriteCnt-1 do begin logStr := logStr + Format('%2.2x ', [data[bufferOffset+cnt]]); end; // update the log MbiCallbackOnLog(logStr); // update loop variables len := len - currentWriteCnt; bufferOffset := bufferOffset + currentWriteCnt; end; end; //*** end of LogData *** //*************************************************************************************** // NAME: OnTimeout // PARAMETER: none // RETURN VALUE: none // DESCRIPTION: Timer event handler. A timer is used in this example to simulate the // progress of a file download. It also demonstrates how to use the // application callbacks to keep the application informed. // //*************************************************************************************** procedure TEventHandlers.OnTimeout(Sender: TObject); var errorInfo : string; progress : longword; regionCnt : longword; currentWriteCnt : word; bufferOffset : longword; addr : longword; len : longword; dataSizeKB : real; begin timer.Enabled := False; // connect the transport layer MbiCallbackOnLog('Connecting the transport layer. t='+TimeToStr(Time)); loader.Connect; //---------------- start the programming session -------------------------------------- MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); if not loader.StartProgrammingSession then begin // update the user info MbiCallbackOnInfo('Could not connect. Please reset your target...'); MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); Application.ProcessMessages; end; while not loader.StartProgrammingSession do begin Application.ProcessMessages; Sleep(5); if stopRequest then begin MbiCallbackOnError('Programming session cancelled by user.'); Exit; end; end; // still here so programming session was started MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); // create the datafile object datafile := TXcpDataFile.Create(progfile); // compute the size in kbytes dataSizeKB := datafile.GetDataCnt / 1024; // Call application callback when we start the actual download MbiCallbackOnStarted(datafile.GetDataCnt); // Init progress to 0 progress progress := 0; MbiCallbackOnProgress(progress); //---------------- next clear the memory regions -------------------------------------- // update the user info MbiCallbackOnInfo('Erasing memory...'); for regionCnt := 0 to datafile.GetRegionCnt-1 do begin // obtain the region info datafile.GetRegionInfo(regionCnt, addr, len); // erase the memory MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); if not loader.ClearMemory(addr, len) then begin loader.GetLastError(errorInfo); MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); datafile.Free; Exit; end; MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); end; //---------------- next program the memory regions ------------------------------------ for regionCnt := 0 to datafile.GetRegionCnt-1 do begin // update the user info MbiCallbackOnInfo('Reading file...'); // obtain the region info datafile.GetRegionInfo(regionCnt, addr, len); // dynamically allocated buffer memory SetLength(progdata, len); // obtain the regiond data datafile.GetRegionData(regionCnt, progdata); bufferOffset := 0; while len > 0 do begin // set the current write length taking into account kMaxProgLen currentWriteCnt := len mod kMaxProgLen; if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; // program the data MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); LogData(@progdata[bufferOffset], currentWriteCnt); if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then begin loader.GetLastError(errorInfo); MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); MbiCallbackOnError('Could not program data ('+errorInfo+').'); datafile.Free; Exit; end; MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); // update progress progress := progress + currentWriteCnt; MbiCallbackOnProgress(progress); // update loop variables len := len - currentWriteCnt; addr := addr + currentWriteCnt; bufferOffset := bufferOffset + currentWriteCnt; // update the user info MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); end; end; //---------------- stop the programming session --------------------------------------- MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); if not loader.StopProgrammingSession then begin loader.GetLastError(errorInfo); MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); datafile.Free; Exit; end; MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); // all done so set progress to 100% and finish up progress := datafile.GetDataCnt; datafile.Free; MbiCallbackOnProgress(progress); MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); MbiCallbackOnDone; end; //*** end of OnTimeout *** //*************************************************************************************** // NAME: MbiInit // PARAMETER: callback function pointers // RETURN VALUE: none // DESCRIPTION: Called by the application to initialize the interface library. // //*************************************************************************************** procedure MbiInit(cbStarted: TStartedEvent; cbProgress: TProgressEvent; cbDone: TDoneEvent; cbError: TErrorEvent; cbLog: TLogEvent; cbInfo: TInfoEvent); stdcall; begin //--- begin of don't change --- AppOnStarted := cbStarted; AppOnProgress := cbProgress; AppOnDone := cbDone; AppOnLog := cbLog; AppOnInfo := cbInfo; AppOnError := cbError; //--- end of don't change --- // create xcp loader object loader := TXcpLoader.Create; // update to the latest configuration loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); // create and init a timer events := TEventHandlers.Create; timer := TTimer.Create(nil); timer.Enabled := False; timer.Interval := 100; timer.OnTimer := events.OnTimeout; end; //*** end of MbiInit *** //*************************************************************************************** // NAME: MbiStart // PARAMETER: filename of the file that is to be downloaded. // RETURN VALUE: none // DESCRIPTION: Called by the application to request the interface library to download // the file that is passed as a parameter. // //*************************************************************************************** procedure MbiStart(fileName: ShortString); stdcall; begin // update the user info MbiCallbackOnInfo(''); // start the log MbiCallbackOnLog('--- Downloading "'+fileName+'" ---'); // reset stop request stopRequest := false; // start the startup timer which gives microBoot a chance to paint itself timer.Enabled := True; // store the program's filename progfile := fileName; end; //*** end of MbiStart *** //*************************************************************************************** // NAME: MbiStop // PARAMETER: none // RETURN VALUE: none // DESCRIPTION: Called by the application to request the interface library to stop // a download that could be in progress. // //*************************************************************************************** procedure MbiStop; stdcall; begin // set stop request stopRequest := true; // disconnect the transport layer MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); loader.Disconnect; end; //*** end of MbiStop *** //*************************************************************************************** // NAME: MbiDeInit // PARAMETER: none // RETURN VALUE: none // DESCRIPTION: Called by the application to uninitialize the interface library. // //*************************************************************************************** procedure MbiDeInit; stdcall; begin // release xcp loader object loader.Free; // release the timer and events object timer.Free; events.Free; //--- begin of don't change --- AppOnStarted := nil; AppOnProgress := nil; AppOnDone := nil; AppOnLog := nil; AppOnInfo := nil; AppOnError := nil; //--- end of don't change --- end; //*** end of MbiDeInit *** //*************************************************************************************** // NAME: MbiName // PARAMETER: none // RETURN VALUE: name of the interface library // DESCRIPTION: Called by the application to obtain the name of the interface library. // //*************************************************************************************** function MbiName : ShortString; stdcall; begin Result := 'OpenBLT CAN Vector'; end; //*** end of MbiName *** //*************************************************************************************** // NAME: MbiDescription // PARAMETER: none // RETURN VALUE: description of the interface library // DESCRIPTION: Called by the application to obtain the description of the interface // library. // //*************************************************************************************** function MbiDescription : ShortString; stdcall; begin Result := 'OpenBLT using Vector CAN Interface'; end; //*** end of MbiDescription *** //*************************************************************************************** // NAME: MbiVersion // PARAMETER: none // RETURN VALUE: version number // DESCRIPTION: Called by the application to obtain the version number of the // interface library. // //*************************************************************************************** function MbiVersion : Longword; stdcall; begin Result := 10000; // v1.00.00 end; //*** end of MbiVersion *** //*************************************************************************************** // NAME: MbiVInterface // PARAMETER: none // RETURN VALUE: version number of the supported interface // DESCRIPTION: Called by the application to obtain the version number of the // Mbi interface uBootInterface.pas (not the interface library). This can // be used by the application for backward compatibility. // //*************************************************************************************** function MbiVInterface : Longword; stdcall; begin Result := 10001; // v1.00.01 end; //*** end of MbiVInterface *** //*************************************************************************************** // NAME: MbiConfigure // PARAMETER: none // RETURN VALUE: none // DESCRIPTION: Called by the application to enable the user to configure the inter- // face library through the application. // //*************************************************************************************** procedure MbiConfigure; stdcall; var settings : TXcpSettings; begin // create xcp settings object settings := TXcpSettings.Create(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); // display the modal configuration dialog settings.Configure; // release the xcp settings object settings.Free; // update to the latest configuration loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); end; //*** end of MbiConfigure *** //*************************************************************************************** // External Declarations //*************************************************************************************** exports //--- begin of don't change --- MbiInit index 1, MbiStart index 2, MbiStop index 3, MbiDeInit index 4, MbiName index 5, MbiDescription index 6, MbiVersion index 7, MbiConfigure index 8, MbiVInterface index 9; //--- end of don't change --- end. //********************************** end of openblt_can_vector.dpr **********************