diff options
| author | Tero Kontkanen <tero.kontkanen@granitedevices.fi> | 2017-04-06 17:06:50 +0300 |
|---|---|---|
| committer | Tero Kontkanen <tero.kontkanen@granitedevices.fi> | 2017-04-06 17:06:50 +0300 |
| commit | 1d6f69d1f056777401bcdfcde0844c9b9af1cbac (patch) | |
| tree | ebb622f228b0ffc30bc9b416a5225c4c9bf9969b /smdeploymenttool.c | |
| parent | a780e4b1123dbc416dd06af9ee2d7f99f281a9c7 (diff) | |
| download | SimpleMotionV2-1d6f69d1f056777401bcdfcde0844c9b9af1cbac.tar.gz SimpleMotionV2-1d6f69d1f056777401bcdfcde0844c9b9af1cbac.zip | |
Update readme.md & rename library files
Diffstat (limited to 'smdeploymenttool.c')
| -rw-r--r-- | smdeploymenttool.c | 654 |
1 files changed, 0 insertions, 654 deletions
diff --git a/smdeploymenttool.c b/smdeploymenttool.c deleted file mode 100644 index 2551128..0000000 --- a/smdeploymenttool.c +++ /dev/null @@ -1,654 +0,0 @@ -#include "smdeploymenttool.h" -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <simplemotion_private.h> -#include <math.h> - -#ifdef __unix__ -#include <unistd.h> -void sleep_ms(int millisecs) -{ - msleep(millisecs); -} -#else -#include <windows.h> -void sleep_ms(int millisecs) -{ - Sleep(millisecs); -} -#endif - -int globalErrorDetailCode=0; - -int smGetDeploymentToolErrroDetail() -{ - return globalErrorDetailCode; -} - -//return -1 if EOF -unsigned int readFileLine( FILE *f, int charlimit, char *output, smbool *eof) -{ - int len=0; - char c; - do - { - c=fgetc(f); - - if(feof(f)) - *eof=smtrue; - else - *eof=smfalse; - - //eol or eof - if( *eof==smtrue || c=='\n' || c=='\r' || len>=charlimit-1 ) - { - output[len]=0;//terminate str - return len; - } - - output[len]=c; - len++; - } while(1); - return len; -} - -typedef struct -{ - int address; - double value; - smbool readOnly; - double scale; - double offset; -} Parameter; - -smbool parseParameter(FILE *f, int idx, Parameter *param ) -{ - const int maxLineLen=100; - char line[maxLineLen]; - char scanline[maxLineLen]; - //search correct row - fseek(f,0,SEEK_SET); - smbool gotaddr=smfalse,gotvalue=smfalse, gotreadonly=smfalse, gotscale=smfalse,gotoffset=smfalse; - unsigned int readbytes; - smbool eof; - - do//loop trhu all lines of file - { - readbytes=readFileLine(f,maxLineLen,line,&eof);//read line - - //try read address - sprintf(scanline,"%d\\addr=",idx); - if(!strncmp(line,scanline,strlen(scanline)) && readbytes > strlen(scanline))//string starts with correct line - if(sscanf(line+strlen(scanline),"%d",¶m->address)==1)//parse number after the start of line - gotaddr=smtrue;//number parse success - - //try read value - sprintf(scanline,"%d\\value=",idx); - if(!strncmp(line,scanline,strlen(scanline)) && readbytes > strlen(scanline))//string starts with correct line - if(sscanf(line+strlen(scanline),"%lf",¶m->value)==1)//parse number after the start of line - gotvalue=smtrue;//number parse success - - //try read offset - sprintf(scanline,"%d\\offset=",idx); - if(!strncmp(line,scanline,strlen(scanline)) && readbytes > strlen(scanline))//string starts with correct line - if(sscanf(line+strlen(scanline),"%lf",¶m->offset)==1)//parse number after the start of line - gotoffset=smtrue;//number parse success - - //try read scale - sprintf(scanline,"%d\\scaling=",idx); - if(!strncmp(line,scanline,strlen(scanline)) && readbytes > strlen(scanline))//string starts with correct line - if(sscanf(line+strlen(scanline),"%lf",¶m->scale)==1)//parse number after the start of line - gotscale=smtrue;//number parse success - - //try read readonly status - sprintf(scanline,"%d\\readonly=true",idx);//check if readonly=true - if(!strncmp(line,scanline,strlen(scanline)) && readbytes >= strlen(scanline))//line match - { - param->readOnly=smtrue; - gotreadonly=smtrue; - } - sprintf(scanline,"%d\\readonly=false",idx);//check if readonly=false - if(!strncmp(line,scanline,strlen(scanline)) && readbytes >= strlen(scanline))//line match - { - param->readOnly=smfalse; - gotreadonly=smtrue; - } - } - while( (gotvalue==smfalse || gotaddr==smfalse || gotreadonly==smfalse || gotscale==smfalse || gotoffset==smfalse) && eof==smfalse ); - - if(gotvalue==smtrue&&gotaddr==smtrue&&gotoffset==smtrue&&gotscale==smtrue&&gotreadonly==smtrue) - { - return smtrue; - } - - return smfalse;//not found -} - -/** - * @brief smConfigureParameters Configures all target device parameters from file and performs device restart if necessary. This can take few seconds to complete. This may take 2-5 seconds to call. - * @param smhandle SM bus handle, must be opened before call - * @param smaddress Target SM device address - * @param filename .DRC file name - * @param mode Combined from CONFIGMODE_ define bits (can logic OR mutliple values). - * @return Enum LoadConfigurationStatus - * - * Requires DRC file version 111 or later to use CONFIGMODE_REQUIRE_SAME_FW. - */ -LoadConfigurationStatus smLoadConfiguration(const smbus smhandle, const int smaddress, const char *filename, unsigned int mode , int *skippedCount, int *errorCount) -{ - //test connection - smint32 devicetype; - SM_STATUS stat; - FILE *f; - int ignoredCount=0; - int setErrors=0; - smint32 CB1Value; - int changed=0; - - *skippedCount=-1; - *errorCount=-1; - - //test connection - stat=smRead1Parameter(smhandle,smaddress,SMP_DEVICE_TYPE,&devicetype); - if(stat!=SM_OK) - return CFGCommunicationError; - - //smSetParameter( smhandle, smaddress, SMP_RETURN_PARAM_LEN, SMPRET_CMD_STATUS );//get command status as feedback from each executed SM command - - if(mode&CONFIGMODE_DISABLE_DURING_CONFIG) - { - smRead1Parameter( smhandle, smaddress, SMP_CONTROL_BITS1, &CB1Value ); - smSetParameter( smhandle, smaddress, SMP_CONTROL_BITS1, 0);//disable drive - } - - if(getCumulativeStatus( smhandle )!=SM_OK ) - return CFGCommunicationError; - - f=fopen(filename,"rb"); - if(f==NULL) - return CFGUnableToOpenFile; - - smDebug(smhandle,Low,"Setting parameters\n"); - - int i=1; - smbool readOk; - do - { - Parameter param; - readOk=parseParameter(f,i,¶m); - - if(readOk==smtrue && param.readOnly==smfalse) - { - smint32 currentValue; - - int configFileValue=round(param.value*param.scale-param.offset); - - //set parameter to device - if(smRead1Parameter( smhandle, smaddress, param.address, ¤tValue )==SM_OK) - { - if(currentValue!=configFileValue ) //set only if different - { - resetCumulativeStatus( smhandle ); - smint32 dummy; - smint32 cmdSetAddressStatus; - smint32 cmdSetValueStatus; - - //use low level SM commands so we can get execution status of each subpacet: - smAppendSMCommandToQueue( smhandle, SM_SET_WRITE_ADDRESS, SMP_RETURN_PARAM_LEN ); - smAppendSMCommandToQueue( smhandle, SM_WRITE_VALUE_24B, SMPRET_CMD_STATUS ); - smAppendSMCommandToQueue( smhandle, SM_SET_WRITE_ADDRESS, param.address ); - smAppendSMCommandToQueue( smhandle, SM_WRITE_VALUE_32B, configFileValue ); - smExecuteCommandQueue( smhandle, smaddress ); - smGetQueuedSMCommandReturnValue( smhandle, &dummy ); - smGetQueuedSMCommandReturnValue( smhandle, &dummy ); - smGetQueuedSMCommandReturnValue( smhandle, &cmdSetAddressStatus ); - smGetQueuedSMCommandReturnValue( smhandle, &cmdSetValueStatus ); - - //check if above code succeed - if( getCumulativeStatus(smhandle)!=SM_OK || cmdSetAddressStatus!=SMP_CMD_STATUS_ACK || cmdSetValueStatus!=SMP_CMD_STATUS_ACK ) - { - SM_STATUS stat=getCumulativeStatus(smhandle); - setErrors++; - smDebug(smhandle,Low,"Failed to write parameter value %d to address %d (status: %d %d %d)\n",configFileValue,param.address,(int)stat,cmdSetAddressStatus,cmdSetValueStatus); - } - - changed++; - } - } - else//device doesn't have such parameter. perhaps wrong model or fw version. - { - ignoredCount++; - smDebug(smhandle,Low,"Ignoring parameter parameter value %d to address %d\n",configFileValue,param.address); - } - } - - i++; - } while(readOk==smtrue); - - *skippedCount=ignoredCount; - *errorCount=setErrors; - - resetCumulativeStatus( smhandle ); - - //save to flash if some value was changed - if(changed>0) - smSetParameter( smhandle, smaddress, SMP_SYSTEM_CONTROL, SMP_SYSTEM_CONTROL_SAVECFG ); - - if(mode&CONFIGMODE_CLEAR_FAULTS_AFTER_CONFIG ) - { - smDebug(smhandle,Low,"Restting faults\n"); - smSetParameter( smhandle, smaddress, SMP_FAULTS, 0 );//reset faults - } - - //re-enable drive - if(mode&CONFIGMODE_DISABLE_DURING_CONFIG) - { - smDebug(smhandle,Low,"Restoring CONTROL_BITS1 to value 0x%x\n",CB1Value); - smSetParameter( smhandle, smaddress, SMP_CONTROL_BITS1, CB1Value );//restore controbits1 (enable if it was enabled before) - } - - smint32 statusbits; - smRead1Parameter( smhandle, smaddress, SMP_STATUS, &statusbits ); - - //restart drive if necessary or if forced - if( (statusbits&STAT_PERMANENT_STOP) || (mode&CONFIGMODE_ALWAYS_RESTART_TARGET) ) - { - smDebug(smhandle,Low,"Restarting device\n"); - smSetParameter( smhandle, smaddress, SMP_SYSTEM_CONTROL, SMP_SYSTEM_CONTROL_RESTART ); - sleep_ms(2000);//wait power-on - } - - if(getCumulativeStatus(smhandle)!=SM_OK) - return CFGCommunicationError; - - return CFGComplete; -} - -/** - * @brief smGetDeviceFirmwareUniqueID Reads installed firmware binary checksum that can be used to verify whether a wanted FW version is installed - * @param smhandle SM bus handle, must be opened before call - * @param smaddress Target SM device address. Can be device in DFU mode or main operating mode. For Argon, one device in a bus must be started into DFU mode by DIP switches and smaddress must be set to 255. - * @param UID result will be written to this pointer - * @return smtrue if success, smfalse if failed (if communication otherwise works, then probably UID feature not present in this firmware version) - */ -smbool smGetDeviceFirmwareUniqueID( smbus smhandle, int deviceaddress, smuint32 *UID )//FIXME gives questionable value if device is in DFU mode. Check FW side. -{ - smint32 fwBinaryChecksum; - resetCumulativeStatus(smhandle); - smSetParameter( smhandle, deviceaddress, SMP_SYSTEM_CONTROL, SMP_SYSTEM_CONTROL_GET_SPECIAL_DATA); - smRead1Parameter( smhandle, deviceaddress, SMP_DEBUGPARAM1, &fwBinaryChecksum ); - *UID=(smuint32) fwBinaryChecksum; - - if(getCumulativeStatus(smhandle)==SM_OK) - return smtrue; - else - return smfalse; -} - -FirmwareUploadStatus verifyFirmwareData(smuint8 *data, smuint32 numbytes, int connectedDeviceTypeId, - smuint32 *primaryMCUDataOffset, smuint32 *primaryMCUDataLenth, - smuint32 *secondaryMCUDataOffset,smuint32 *secondaryMCUDataLength ) -{ - //see http://granitedevices.com/wiki/Argon_firmware_file_format - - smuint32 filetype; - filetype=((smuint32*)data)[0]; - if(filetype!=0x57464447) //check header string "GDFW" - return FWInvalidFile; - - smuint16 filever, deviceid; - smuint32 primaryMCUSize, secondaryMCUSize; - - filever=((smuint16*)data)[2]; - deviceid=((smuint16*)data)[3]; - primaryMCUSize=((smuint32*)data)[2]; - secondaryMCUSize=((smuint32*)data)[3]; - if(secondaryMCUSize==0xffffffff) - secondaryMCUSize=0;//it is not present - - if(filever!=300) - return FWIncompatibleFW; - - if(deviceid/1000!=connectedDeviceTypeId/1000)//compare only device and model family. AABBCC so AAB is compared value, ARGON=004 IONI=011 - return FWIncompatibleFW; - - //get checksum and check it - smuint32 cksum,cksumcalc=0; - smuint32 i; - smuint32 cksumOffset=4+2+2+4+4+primaryMCUSize+secondaryMCUSize; - if(cksumOffset>numbytes-4) - return FWInvalidFile; - cksum=((smuint32*)((smuint32)data+cksumOffset))[0]; - - for(i=0;i< numbytes-4;i++) - { - cksumcalc+=data[i]; - } - - if(cksum!=cksumcalc) - return FWIncompatibleFW; - - //let caller know where the firmware data is located in buffer - *primaryMCUDataOffset=4+2+2+4+4; - *primaryMCUDataLenth=primaryMCUSize; - *secondaryMCUDataOffset=*primaryMCUDataOffset+*primaryMCUDataLenth; - *secondaryMCUDataLength=secondaryMCUSize; - - return FWComplete; -} - -smbool loadBinaryFile( const char *filename, smuint8 **data, int *numbytes ) -{ - FILE *f; - f=fopen(filename,"rb"); - if(f==NULL) - return smfalse; - - *numbytes=0; - - //get length - fseek(f,0,SEEK_END); - int length=ftell(f); - fseek(f,0,SEEK_SET); - - //allocate buffer - *data=malloc(length); - if(*data==NULL) - return smfalse; - - //read - *numbytes=fread(*data,1,length,f); - if(*numbytes!=length)//failed to read it all - { - free(*data); - *numbytes=0; - return smfalse; - } - - return smtrue;//successl -} - - - -//flashing STM32 (host side mcu) -smbool flashFirmwarePrimaryMCU( smbus smhandle, int deviceaddress, const smuint8 *data, smint32 size, int *progress ) -{ - smint32 ret; - static smint32 deviceType, fwVersion; - static int uploadIndex; - int c; - const int BL_CHUNK_LEN=32; - static enum {Init,Upload,Finish} state=Init; - - if(state==Init) - { - resetCumulativeStatus( smhandle ); - smRead2Parameters( smhandle, deviceaddress, SMP_FIRMWARE_VERSION, &fwVersion, SMP_DEVICE_TYPE,&deviceType ); - - if(getCumulativeStatus(smhandle)!=SM_OK) - { - state=Init; - return smfalse; - } - -/* kommentoitu pois koska ei haluta erasoida parskuja koska parametri SMO ei saisi nollautua mielellään - - if(deviceType!=4000)//argon does not support BL function 11 - smSetParameter(smhandle,deviceaddress,SMP_BOOTLOADER_FUNCTION,11);//BL func on ioni 11 = do mass erase on STM32, also confifuration - else//does not reset on ioni and drives that support preserving settings. but resets on argon -*/ - smSetParameter(smhandle,deviceaddress,SMP_BOOTLOADER_FUNCTION,1);//BL func 1 = do mass erase on STM32. On Non-Argon devices it doesn't reset confifuration - - sleep_ms(2000);//wait some time. 500ms too little 800ms barely enough - - //flash - smSetParameter(smhandle,deviceaddress,SMP_RETURN_PARAM_LEN, SMPRET_CMD_STATUS); - - if(getCumulativeStatus(smhandle)!=SM_OK) - { - state=Init; - return smfalse; - } - - state=Upload; - uploadIndex=0; - *progress=5; - } - else if(state==Upload) - { - size/=2;//bytes to 16 bit words - - //upload data in 32=BL_CHUNK_LEN word chunks - for(;uploadIndex<size;) - { - smAppendSMCommandToQueue( smhandle, SMPCMD_SETPARAMADDR, SMP_BOOTLOADER_UPLOAD ); - for(c=0;c<BL_CHUNK_LEN;c++) - { - smuint16 upword; - //pad end of file with constant to make full chunk - if(uploadIndex>=size) - upword=0xeeee; - else - upword=((smuint16*)data)[uploadIndex]; - smAppendSMCommandToQueue( smhandle, SMPCMD_24B, upword ); - uploadIndex++; - } - - smAppendSMCommandToQueue( smhandle, SMPCMD_SETPARAMADDR, SMP_BOOTLOADER_FUNCTION ); - smAppendSMCommandToQueue( smhandle, SMPCMD_24B, 2);//BL func 2 = do write on STM32 - smExecuteCommandQueue( smhandle, deviceaddress ); - - //read return packets - for(c=0;c<BL_CHUNK_LEN+3;c++) - { - smGetQueuedSMCommandReturnValue( smhandle,&ret ); - - if(getCumulativeStatus(smhandle)!=SM_OK) - { - state=Init; - return smfalse; - } - } - - *progress=5+90*uploadIndex/size;//gives value 5-95 - if(*progress>=94)//95 will indicate that progress is complete. dont let it indicate that yet. - *progress=94; - - if(uploadIndex%256==0) - { - //printf("upload %d\n",uploadIndex); - return smtrue;//in progress. return often to make upload non-blocking - } - } - if(uploadIndex>=size)//finished - { - state=Finish; - } - } - else if(state==Finish) - { - //verify STM32 flash if supported by BL version - if(fwVersion>=1210) - { - smSetParameter(smhandle,deviceaddress,SMP_BOOTLOADER_FUNCTION,3);//BL func 3 = verify STM32 FW integrity - smint32 faults; - smRead1Parameter(smhandle,deviceaddress,SMP_FAULTS,&faults); - - if(getCumulativeStatus(smhandle)!=SM_OK) - { - state=Init; - *progress=0; - return smfalse; - } - - if(faults&FLT_FLASHING_COMMSIDE_FAIL) - { - //printf("verify failed\n"); - *progress=0; - state=Init; - return smfalse; - } - else - { - //printf("verify success\n"); - } - } - - *progress=95;//my job is complete - state=Init; - } - - return smtrue; -} - - -typedef enum { StatIdle=0, StatEnterDFU, StatFindDFUDevice, StatLoadFile, StatUpload, StatLaunch } UploadState;//state machine status - -//free buffer and return given status code -FirmwareUploadStatus abortFWUpload( FirmwareUploadStatus stat, smuint8 *fwData, UploadState *state, int errorDetailCode ) -{ - globalErrorDetailCode=errorDetailCode; - *state=StatIdle; - free(fwData); - return stat; -} - -/** - * @brief smFirmwareUpload Sets drive in firmware upgrade mode if necessary and uploads a new firmware. Call this many until it returns value 100 (complete) or a negative value (error). - * @param smhandle SM bus handle, must be opened before call - * @param smaddress Target SM device address. Can be device in DFU mode or main operating mode. For Argon, one device in a bus must be started into DFU mode by DIP switches and smaddress must be set to 255. - * @param filename .gdf file name - * @return Enum FirmwareUploadStatus that indicates errors or Complete status. Typecast to integer to get progress value 0-100. - */ -FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress, const char *firmware_filename ) -{ - static smuint8 *fwData=NULL; - static int fwDataLength; - static smuint32 primaryMCUDataOffset, primaryMCUDataLenth; - static smuint32 secondaryMCUDataOffset,secondaryMCUDataLength; - static UploadState state=StatIdle;//state machine status - static smint32 deviceType=0; - static int DFUAddress; - static int progress=0; - - SM_STATUS stat; - - //state machine - if(state==StatIdle) - { - - //check if device is in DFU mode already - smint32 busMode; - stat=smRead2Parameters(smhandle,smaddress,SMP_BUS_MODE,&busMode, SMP_DEVICE_TYPE, &deviceType); - if(stat==SM_OK && busMode==SMP_BUS_MODE_DFU) - { - state=StatLoadFile; - } - else if(stat==SM_OK && busMode!=0)//device not in bus mode - { - if(deviceType==4000)//argon does not support restarting in DFU mode by software - { - return abortFWUpload(FWConnectionError,fwData,&state,200); - } - - //restart device into DFU mode - state=StatEnterDFU; - - stat=smSetParameter(smhandle,smaddress,SMP_SYSTEM_CONTROL,64);//reset device to DFU command - if(stat!=SM_OK) - return abortFWUpload(FWConnectionError,fwData,&state,300); - } - else - state=StatFindDFUDevice;//search DFU device in brute force, fallback for older BL versions that don't preserve same smaddress than non-DFU mode - //return abortFWUpload(FWConnectionError,fwData,&state,301); - - progress=1; - DFUAddress=smaddress; - } - - else if(state==StatEnterDFU) - { - sleep_ms(2500);//wait device to reboot in DFU mode. probably shorter delay would do. - - //check if device is in DFU mode already - smint32 busMode; - stat=smRead2Parameters(smhandle,smaddress, SMP_BUS_MODE,&busMode, SMP_DEVICE_TYPE, &deviceType); - if(stat==SM_OK && busMode==0)//busmode 0 is DFU mode - { - state=StatLoadFile; - } - else - state=StatFindDFUDevice;//search DFU device in brute force, fallback for older BL versions that don't preserve same smaddress than non-DFU mode - - progress=2; - } - - else if(state==StatFindDFUDevice) - { - int i; - for(i=245;i<=255;i++) - { - smint32 busMode; - stat=smRead2Parameters(smhandle,i, SMP_BUS_MODE,&busMode, SMP_DEVICE_TYPE, &deviceType); - if(stat==SM_OK && busMode==0)//busmode 0 is DFU mode - { - state=StatLoadFile; - DFUAddress=i; - break;//DFU found, break out of for loop - } - } - - if(i==256)//DFU device not found - return abortFWUpload(CFGConnectingDFUModeFailed,fwData,&state,400);//setting DFU mode failed - - progress=3; - } - - else if(state==StatLoadFile) - { - if(loadBinaryFile(firmware_filename,&fwData,&fwDataLength)!=smtrue) - return FWFileNotReadable; - - FirmwareUploadStatus stat=verifyFirmwareData(fwData, fwDataLength, deviceType, - &primaryMCUDataOffset, &primaryMCUDataLenth, - &secondaryMCUDataOffset, &secondaryMCUDataLength); - if(stat!=FWComplete)//error in verify - { - return abortFWUpload(stat,fwData,&state,100); - } - - //all good, upload firmware - state=StatUpload; - - progress=4; - } - - else if(state==StatUpload) - { - smbool ret=flashFirmwarePrimaryMCU(smhandle,DFUAddress,fwData+primaryMCUDataOffset,primaryMCUDataLenth,&progress); - if(ret==smfalse)//failed - { - return abortFWUpload(FWConnectionError,fwData,&state,1000); - } - else - { - if(progress>=95) - state=StatLaunch; - } - } - - else if(state==StatLaunch) - { - smSetParameter(smhandle,DFUAddress,SMP_BOOTLOADER_FUNCTION,4);//BL func 4 = launch. - sleep_ms(2000); - progress=100; - state=StatIdle; - } - - return (FirmwareUploadStatus)progress; -} - - - - |
