cifX : Mise en œuvre : API – Chargement d’un firmware

Bonjour,

Il est possible de réaliser le chargement du firmware des cartes Hilscher cifX via l’API.

Ainsi, nos clients peuvent par exemple mettre à jour le firmware depuis leur propre application en combinant cette mise à jour avec celle de leur application par intégration dans le programme d’installation.

On peut aussi imaginer que l’ensemble des firmwares disponibles soit stocké dans les dossiers de l’application et que la sélection du firmware se fasse depuis l’interface utilisateur de cette application, un peu à la manière du netX Configuration Tool par exemple.

Donc, en prérequis, le pilote cifX est installé et les répertoires de la carte ne contiennent pas de firmware, ce que l’on peut vérifier avec cifXSetup sous Windows.

Au démarrage, le pilote ne va charger que le programme d’amorce dans la carte. Ce programme offre uniquement le canal système et l’on va utiliser celui-ci pour charger notre firmware.

Rien de compliqué ici, le code source présenté ci-dessous effectue les opérations suivantes :

  • lecture du fichier en mode binaire,
  • chargement du firmware via le canal système,
  • démarrage du firmware.
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include "cifxuser.h"
#include "cifxErrors.h"
#include "rcX_Public.h"

#define IO_WAIT_TIMEOUT     10

void ShowError( long lError)
{
  if( lError != CIFX_NO_ERROR)
  {
    // Read driver error description
    char szError[1024] ={0};
    xDriverGetErrorDescription( lError,  szError, sizeof(szError));
    printf("Error: 0x%X, <%s>\r\n", lError, szError);
  }
}

int get_file_size(FILE *hFile)
{
  if (fseek(hFile, 0L, SEEK_END) != 0)
  {
    return (0);
  }
  return ftell(hFile);
}


BOOLEAN DownloadFirmware( HANDLE hDriver)
{
  //------------------------------
  // Load a file
  //------------------------------
  char* pszFileName = "D:\\SLO\\GNAT\\C03\\cifX\\cifxdps.nxf";
  unsigned char* pabFileData = NULL;

  FILE      *hFile           = NULL;
  int       iFileSize        = 0;
  int       iBytesRead       = 0;
  long      lRet             = CIFX_NO_ERROR;
  BOOLEAN   fDownloadSuccess = FALSE;
  HANDLE    hSysDevice       = NULL;

  CIFX_PACKET   tSendPacket     = {0};
  CIFX_PACKET   tRecvPacket     = {0};

  RCX_CHANNEL_INSTANTIATE_REQ_DATA_T *pChannelInstantiateReqData;

  hFile = fopen(pszFileName, "rb");
  if ( hFile == NULL)
  {
    // Error opening the file
    printf("DownloadFirmware(): File <%s> open error\r\n", pszFileName);
    return FALSE;
  }

  iFileSize = get_file_size(hFile);
  printf("DownloadFirmware(): File size is %i\r\n", iFileSize);
  if ( iFileSize == 0 )
  {
    fclose(hFile);
    return FALSE;
  }

  pabFileData = (unsigned char *)malloc(iFileSize);
  if (pabFileData == NULL)
  {
    printf("DownloadFirmware(): could not malloc\r\n");
  }

  if (fseek(hFile, 0L, SEEK_SET) != 0) {
    printf("DownloadFirmware(): could not rewind\r\n");
    fclose(hFile);
    free(pabFileData);
    return FALSE;
  }

  iBytesRead = fread(pabFileData, (size_t)1, iFileSize, hFile);
  if ( iBytesRead != iFileSize)
  {
    printf("DownloadFirmware(): iBytesRead != iFileSize (%i != %i)\r\n",
           iBytesRead, iFileSize);

    fclose(hFile);
    free(pabFileData);
    return FALSE;
  }

  //------------------------------
  // Download firmware
  //------------------------------

  lRet = xSysdeviceOpen( hDriver, "CifX0", &hSysDevice);
  if(lRet != CIFX_NO_ERROR)
  {
    ShowError( lRet);
  } else
  {
    printf("DownloadFirmware(): downloading file...\r\n");
    lRet = xSysdeviceDownload( hSysDevice, 0, DOWNLOAD_MODE_FIRMWARE,
                              "cifxdps.nxf", pabFileData, iFileSize,
                              NULL, NULL, NULL);
    if(lRet != CIFX_NO_ERROR)
    {
      ShowError( lRet);
    } else
    {
      /*Start Firmware Request*/
      tSendPacket.tHeader.ulDest  = 0; /*System*/
      tSendPacket.tHeader.ulSrc   = 0;
      tSendPacket.tHeader.ulDestId= 0; /*System*/
      tSendPacket.tHeader.ulSrcId = 0;
      tSendPacket.tHeader.ulLen   = 4;
      tSendPacket.tHeader.ulId    = 1;
      tSendPacket.tHeader.ulState = 0;
      tSendPacket.tHeader.ulCmd   = RCX_CHANNEL_INSTANTIATE_REQ;
      tSendPacket.tHeader.ulExt   = 0;
      tSendPacket.tHeader.ulRout  = 0;

      pChannelInstantiateReqData = (RCX_CHANNEL_INSTANTIATE_REQ_DATA_T *)tSendPacket.abData;
      pChannelInstantiateReqData->ulChannelNo  = 0;

      printf("DownloadFirmware(): Starting firmware...\r\n");
      lRet = xSysdevicePutPacket(hSysDevice, &tSendPacket, 1000);
      if(CIFX_NO_ERROR != lRet)
      {
        ShowError( lRet);
      }
      else
      {
        lRet = xSysdeviceGetPacket(hSysDevice, sizeof(tRecvPacket), &tRecvPacket, 1000);
        if(CIFX_NO_ERROR != lRet)
        {
          ShowError( lRet);
        }
        else
        {
          printf( "Received Packet\n" \
                 "---------------\n" \
                 "Source : 0x%08X\n" \
                 "Dest   : 0x%08X\n" \
                 "Cmd    : 0x%08X\n" \
                 "Len    : 0x%08X\n" \
                 "Id     : 0x%08X\n" \
                 "State  : 0x%08X\n" \
                 "Ext    : 0x%08X\n" \
                 "lRet   : 0x%X\n",
                 tRecvPacket.tHeader.ulSrc,   tRecvPacket.tHeader.ulDest,
                 tRecvPacket.tHeader.ulCmd,   tRecvPacket.tHeader.ulLen,
                 tRecvPacket.tHeader.ulId,
                 tRecvPacket.tHeader.ulState, tRecvPacket.tHeader.ulExt,
                 lRet);

          if((tRecvPacket.tHeader.ulCmd == RCX_CHANNEL_INSTANTIATE_CNF)
             && (tRecvPacket.tHeader.ulState == 0))
          {
            fDownloadSuccess = TRUE;
          }
        }
      }
    }

    printf("DownloadFirmware(): Closing SysDevice\r\n");
    lRet = xSysdeviceClose(hSysDevice);
    if(lRet != CIFX_NO_ERROR)
    {
      ShowError( lRet);
    }
  }

  fclose(hFile);
  free(pabFileData);
  return fDownloadSuccess;
}

/*****************************************************************************/
/*! The main function
 *   \return 0 on success                                                     */

/*****************************************************************************/
int main(int argc, char* argv[])
{
  HANDLE hDriver  = NULL;
  HANDLE hChannel = NULL;
  long   lRet     = CIFX_NO_ERROR;

  UNREFERENCED_PARAMETER(argc);
  UNREFERENCED_PARAMETER(argv);

  /* Open the cifX driver */
  lRet = xDriverOpen(&hDriver);
  if(CIFX_NO_ERROR != lRet)
  {
    ShowError( lRet);
  } else
  {
    if (DownloadFirmware(hDriver) == TRUE)
    {
      printf("DownloadFirmware(): success\r\n");
    }
    else
    {
      printf("DownloadFirmware(): bullshit\r\n");
    }
    /* Close the cifX driver */
    xDriverClose(hDriver);
  }
  return 0;
}

Bien sûr, il faudra également configurer la carte cifX, soit en chargeant les fichiers de configuration issus des outils fournis, SYCON.net ou netX Configuration Tool, ou par programme avec les fonctions de l’API cifX, comme expliqué ici par exemple.

N’hésitez pas à nous solliciter si besoin.

Cordialement,
Stéphane