initFlsh.c -- Controller initialization and automatic firmware download
/* initFlsh.c */
/* Copyright(c) 1991-2002 Motion Engineering, Inc. All rights reserved.
*
* This software contains proprietary and confidential information of
* Motion Engineering Inc., and its suppliers. Except as may be set forth
* in the license agreement under which this software is supplied, use,
* disclosure, or reproduction is prohibited without the prior express
* written consent of Motion Engineering, Inc.
*/
#if defined(MEI_RCS)
static const char MEIUtilRCS[] =
"$Header: /MainTree/XMPLib/XMP/app/initFlsh.c 4 7/23/01 2:36p Kevinh $";
#endif
/*
:Controller initialization and automatic firmware download
********************************* Warning ***********************************
This application will overwrite the controller configuration that is saved
to the Flash memory. If connected to hardware this could cause motors to
be enabled or to run away. Do NOT use without proper knowledge of the system
*****************************************************************************
This sample code demonstrates how to download Firmware to the XMP-Series
controller. The Firmware can also be downloaded using one of the utilities
provided by MEI. This sample application requires the user to specify the
location and filename for a valid, matching Firmware file and optional
FPGA file(s). During initialization the controller's firmware version,
revision, option and user version numbers are checked. If the controller's
version doesn't match the expected version, the firmware is downloaded to
the controller's flash memory.
Note: The flash utility program uses the same code to download firmware to the
flash memory.
Warning! This is a sample program to assist in the integration of the
XMP motion controller with your application. It may not contain all
of the logic and safety features that your application requires.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"
/* Set desired Firmware version. these values could be read from a file */
#define FW_VERSION 332
#define FW_REVISION 'A'
#define FW_SUBREVISION 2
#define FW_OPTION 0
#define FW_VERSION_USER 0 /* user configurable */
#if defined(ARG_MAIN_RENAME)
#define main initFlshMain
argMainRENAME(main, initFlsh)
#endif
#define FIRMWARE "c:\\xmp332a2.bin" /* this string could be read from a file */
#define FPGA0 (NULL) /* specify NULL for default FPGA image */
#define FPGA1 (NULL)
#define FPGA2 (NULL)
long initXmp(MPIControl control, MEIFlashFiles *fileNames);
int
main(int argc,
char *argv[])
{
MPIControl control;
long returnValue;
long argIndex;
MPIControlType controlType;
MPIControlAddress controlAddress;
MEIFlashFiles flashFiles;
/* Parse command line for Control type and address */
argIndex =
argControl(argc,
argv,
&controlType,
&controlAddress);
/* Obtain a Control handle */
control =
mpiControlCreate(controlType,
&controlAddress);
msgCHECK(mpiControlValidate(control));
/* copy file names into structure */
if (FIRMWARE != NULL) {
strcpy(flashFiles.binFile, FIRMWARE);
}
else {
flashFiles.binFile[0] = '\0';
}
if (FPGA0 != NULL) {
strcpy(flashFiles.FPGAFile[0], FPGA0);
}
else {
flashFiles.FPGAFile[0][0] = '\0';
}
if (FPGA1 != NULL) {
strcpy(flashFiles.FPGAFile[1], FPGA1);
}
else {
flashFiles.FPGAFile[1][0] = '\0';
}
if (FPGA2 != NULL) {
strcpy(flashFiles.FPGAFile[2], FPGA2);
}
else {
flashFiles.FPGAFile[2][0] = '\0';
}
/* Initialize the controller, load flash if firmware is different */
returnValue =
initXmp(control,
&flashFiles); /* firmware and FPGA file name(s) */
msgCHECK(returnValue);
/* Delete object handles */
returnValue = mpiControlDelete(control);
msgCHECK(returnValue);
return ((int)returnValue);
}
long versionCheck(MPIControl control)
{
MPIControlConfig controlConfig;
MEIControlVersion version;
long returnValue;
returnValue =
mpiControlConfigGet(control,
&controlConfig,
NULL);
returnValue =
meiControlVersionGet(control,
&version);
if ((version.xmp.firmware.version != FW_VERSION)
|| (version.xmp.firmware.revision != FW_REVISION)
|| (version.xmp.firmware.subRevision != FW_SUBREVISION)
|| (version.xmp.firmware.option != FW_OPTION)
|| (controlConfig.userVersion != FW_VERSION_USER)) {
meiPlatformConsole("ERROR: Controller firmware does not match expected version.\n"
" Version: %d%c%d option:%d user:%d\n"
" Expected: %d%c%d option:%d user:%d\n\n",
version.xmp.firmware.version,
version.xmp.firmware.revision,
version.xmp.firmware.subRevision,
version.xmp.firmware.option,
controlConfig.userVersion,
FW_VERSION,
FW_REVISION,
FW_SUBREVISION,
FW_OPTION,
FW_VERSION_USER);
returnValue = MEIControlMessageFIRMWARE_VERSION;
}
/* display check result */
meiPlatformConsole("Firmware Version Check: %s\n", mpiMessage(returnValue, NULL));
return (returnValue);
}
long firmwareLoad(MPIControl control, MEIFlashFiles *fileNames)
{
MEIFlash flash;
MEIFlashFiles loadedFiles;
MEIControlVersion version;
long MB0 = -1;
long MB1 = -1;
long update20Khz = 0;
long returnValue;
returnValue =
mpiControlValidate(control);
if (returnValue == MPIMessageOK) {
/* fake a valid version so we can still use the MPI routines */
returnValue =
meiControlVersionGet(control,
&version);
if (returnValue == MPIMessageOK) {
memset(&version.xmp.firmware,
0,
sizeof(version.xmp.firmware));
version.xmp.firmware.version = version.mpi.firmware.version;
version.xmp.firmware.option = version.mpi.firmware.option;
returnValue =
meiControlVersionSet(control,
&version);
}
}
if (returnValue == MPIMessageOK) {
/* Create Flash object */
flash =
meiFlashCreate(control);
returnValue = meiFlashValidate(flash);
}
if (returnValue == MPIMessageOK) {
meiPlatformConsole("Loading flash memory from \"%s\" ...\n",
fileNames->binFile);
}
if (returnValue == MPIMessageOK) {
/* Load Firmware and FPGAs from file(s) */
returnValue =
meiFlashMemoryFromFile(flash,
fileNames,
&loadedFiles);
}
if (returnValue == MPIMessageOK) {
meiPlatformConsole("Code loaded and verified from \"%s\".\n",
loadedFiles.binFile);
meiPlatformConsole("FPGAs loaded and verified from\n"
"%s\n"
"%s\n"
"%s\n\n",
loadedFiles.FPGAFile[0],
loadedFiles.FPGAFile[1],
loadedFiles.FPGAFile[2]);
}
else {
meiPlatformConsole("Can't load flash from \"%s\"\n"
"\"%s\"\n"
"\"%s\"\n"
"\"%s\"\n"
"(%s)\n",
loadedFiles.binFile,
loadedFiles.FPGAFile[0],
loadedFiles.FPGAFile[1],
loadedFiles.FPGAFile[2],
mpiMessage(returnValue, NULL));
}
if (returnValue == MPIMessageOK) {
returnValue = mpiControlReset(control);
msgCHECK(returnValue);
}
if (returnValue == MPIMessageOK) {
MEIControlSocketInfo socketInfo;
MEIControlRipTideConfig config;
returnValue = meiControlSocketInfoGet(control,
&socketInfo);
msgCHECK(returnValue);
/* Get default RipTide configuration */
returnValue = meiControlRipTideDefaultGet(control,
&socketInfo,
&config);
msgCHECK(returnValue);
/* Configure RipTide */
if (MB0 != -1) {
config.motionBlocks[0] = MB0;
}
if (MB1 != -1) {
config.motionBlocks[1] = MB1;
}
config.update20khz = update20Khz;
if (config.update20khz) {
MPIControlConfig controlConfig;
config.motionBlocks[0] = 1;
config.motionBlocks[1] = 0;
/* Set Sample Rate */
returnValue = mpiControlFlashConfigGet(control,
NULL,
&controlConfig,
NULL);
msgCHECK(returnValue);
if (returnValue == MPIMessageOK) {
controlConfig.sampleRate = 20000;
returnValue = mpiControlFlashConfigSet(control,
NULL,
&controlConfig,
NULL);
msgCHECK(returnValue);
}
}
if (returnValue == MPIMessageOK) {
meiPlatformConsole("Configuring RipTide\n");
returnValue = meiControlFlashRipTideConfigSet(control,
flash,
&config);
if (config.update20khz) {
meiPlatformConsole("Reconfigured RipTide:\n"
"Configured for 20Khz operation\n"
"Main Board has 1 Motion Block\n"
"Expansion Board has 0 Motion Blocks\n\n");
}
else {
meiPlatformConsole("Reconfigured RipTide:\n"
"Main Board has %d Motion Blocks\n"
"Expansion Board has %d Motion Blocks\n\n",
config.motionBlocks[0],
config.motionBlocks[1]);
}
}
}
/* clean up */
if (returnValue == MPIMessageOK) {
returnValue = meiFlashDelete(flash);
}
/* re-initialize controller */
if (returnValue == MPIMessageOK) {
returnValue =
mpiControlInit(control);
}
/* check version values */
if (returnValue == MPIMessageOK) {
returnValue =
versionCheck(control);
}
return returnValue;
}
long initXmp(MPIControl control, MEIFlashFiles *fileNames)
{
long returnValue;
/* Initialize the controller */
returnValue =
mpiControlInit(control);
/* check init returnValue */
if ((returnValue == MEIControlMessageFIRMWARE_INVALID) ||
(returnValue == MEIControlMessageFIRMWARE_VERSION) ||
(returnValue == MEIControlMessageFIRMWARE_VERSION_NONE)) {
/* display warning */
meiPlatformConsole("WARNING: %s\n\n",
mpiMessage(returnValue, NULL));
/* load firmware */
returnValue =
firmwareLoad(control, fileNames);
}
else {
if (returnValue == MPIMessageOK) {
/* check firmware version, revision, option, and user version */
returnValue =
versionCheck(control);
if (returnValue == MEIControlMessageFIRMWARE_VERSION) {
/* load firmware */
returnValue =
firmwareLoad(control, fileNames);
}
}
}
return (returnValue);
}