Added version check prototype
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 8s

This commit is contained in:
2025-08-22 08:46:30 +02:00
parent 21a73717a5
commit 27f7cc8602

View File

@@ -12,6 +12,18 @@
#include <string>
#include <unistd.h>
/*
These two constants store the major and the minor firmware version this driver
needs. The following constraints need to be fulfilled:
Actual major version == FIRMWARE_MAJOR_VERSION
Actual minor version >= FIRMWARE_MINOR_VERSION
If one of these constraints is not fulfilled, the driver will shut down the IOC.
If the firmware version cannot be read (e.g. because the variable used to do so
does not exist yet), the conditions outlined above are seen as fulfilled.
*/
const int FIRMWARE_MAJOR_VERSION = 2;
const int FIRMWARE_MINOR_VERSION = 2;
struct masterMacsControllerImpl {
double comTimeout;
@@ -65,6 +77,7 @@ masterMacsController::masterMacsController(const char *portName,
// Initialization of local variables
asynStatus status = asynSuccess;
char response[MAXBUF_] = {0};
pMasterMacsC_ =
std::make_unique<masterMacsControllerImpl>((masterMacsControllerImpl){
@@ -116,6 +129,55 @@ masterMacsController::masterMacsController(const char *portName,
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
exit(-1);
}
// =========================================================================
// Check the firmware version according to the conditions outlined in the
// comment for FIRMWARE_MAJOR_VERSION and FIRMWARE_MINOR_VERSION
status = read(0, 99, response);
if (status == asynSuccess) {
// Just interpret the version if the variable already exists
double versionRaw = 0.0;
int nvals = sscanf(response, "%lf", &versionRaw);
if (nvals == 1 && versionRaw != 0.0) {
// Discard decimal part
long long versionInt = (long long)versionRaw;
// Extract bugfix (last 3 digits)
// Currently not used, just here for completions sake
// int bugfix = versionInt % 1000;
versionInt /= 1000;
// Extract minor (next 3 digits)
int minor = versionInt % 1000;
versionInt /= 1000;
// Remaining is major
int major = (int)versionInt;
// Compare to target values
if (FIRMWARE_MAJOR_VERSION != major ||
FIRMWARE_MINOR_VERSION > minor) {
asynPrint(
this->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (Incorrect "
"version number of firmware: Expected major version equal "
"to %d, got %d. Expected minor version equal to or larger "
"than %d, got %d).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
FIRMWARE_MAJOR_VERSION, major, FIRMWARE_MINOR_VERSION,
minor);
exit(-1);
}
}
} else {
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nCould not read firmware "
"version\n",
portName, __PRETTY_FUNCTION__, __LINE__);
}
}
/*
@@ -199,12 +261,6 @@ asynStatus masterMacsController::writeRead(int axisNo, int tcpCmd,
comTimeout = pMasterMacsC_->comTimeout;
}
masterMacsAxis *axis = getMasterMacsAxis(axisNo);
if (axis == nullptr) {
// We already did the error logging directly in getAxis
return asynError;
}
// Build the full command depending on the inputs to this function
if (isRead) {
snprintf(fullCommand, MAXBUF_ - 1, "%dR%02d\x0D", axisNo, tcpCmd);
@@ -286,32 +342,39 @@ asynStatus masterMacsController::writeRead(int axisNo, int tcpCmd,
}
// Log the overall status (communication successfull or not)
if (status == asynSuccess) {
setAxisParamChecked(axis, motorStatusCommsError, false);
} else {
if (axisNo != 0) {
masterMacsAxis *axis = getMasterMacsAxis(axisNo);
if (axis == nullptr) {
// We already did the error logging directly in getAxis
return asynError;
}
/*
Since the communication failed, there is the possibility that the
controller is not connected at all to the network. In that case, we
cannot be sure that the information read out in the init method of the
axis is still up-to-date the next time we get a connection. Therefore,
an info flag is set which the axis object can use at the start of its
poll method to try to initialize itself.
*/
axis->setNeedInit(true);
/*
Check if the axis already is in an error communication mode. If
it is not, upstream the error. This is done to avoid "flooding"
the user with different error messages if more than one error
ocurred before an error-free communication
*/
getAxisParamChecked(axis, motorStatusProblem, &motorStatusProblem);
if (motorStatusProblem == 0) {
setAxisParamChecked(axis, motorMessageText, drvMessageText);
setAxisParamChecked(axis, motorStatusProblem, true);
if (status == asynSuccess) {
setAxisParamChecked(axis, motorStatusCommsError, false);
} else {
/*
Since the communication failed, there is the possibility that the
controller is not connected at all to the network. In that case, we
cannot be sure that the information read out in the init method of
the axis is still up-to-date the next time we get a connection.
Therefore, an info flag is set which the axis object can use at the
start of its poll method to try to initialize itself.
*/
axis->setNeedInit(true);
/*
Check if the axis already is in an error communication mode. If
it is not, upstream the error. This is done to avoid "flooding"
the user with different error messages if more than one error
ocurred before an error-free communication
*/
getAxisParamChecked(axis, motorStatusProblem, &motorStatusProblem);
if (motorStatusProblem == 0) {
setAxisParamChecked(axis, motorMessageText, drvMessageText);
setAxisParamChecked(axis, motorStatusProblem, true);
setAxisParamChecked(axis, motorStatusCommsError, false);
}
}
}
@@ -334,7 +397,7 @@ asynStatus masterMacsController::parseResponse(
bool responseValid = false;
int responseStart = 0;
asynStatus status = asynSuccess;
int prevConnected = 0;
int prevConnected = 1;
char printableCommand[MAXBUF_] = {0};
char printableResponse[MAXBUF_] = {0};
@@ -342,12 +405,14 @@ asynStatus masterMacsController::parseResponse(
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
masterMacsAxis *axis = getMasterMacsAxis(axisNo);
if (axis == nullptr) {
if (axisNo != 0 && axis == nullptr) {
return asynError;
}
// Was the motor previously connected?
getAxisParamChecked(axis, motorConnected, &prevConnected);
if (axis != nullptr) {
getAxisParamChecked(axis, motorConnected, &prevConnected);
}
// We don't use strlen here since the C string terminator 0x00
// occurs in the middle of the char array.
@@ -371,14 +436,17 @@ asynStatus masterMacsController::parseResponse(
"connected.\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
setAxisParamChecked(axis, motorConnected, true);
status = callParamCallbacks();
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d:\nCould not update parameter library\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
return status;
if (axis != nullptr) {
setAxisParamChecked(axis, motorConnected, true);
status = callParamCallbacks();
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d:\nCould not update parameter library\n",
portName, axisNo, __PRETTY_FUNCTION__,
__LINE__);
return status;
}
}
}
@@ -399,14 +467,17 @@ asynStatus masterMacsController::parseResponse(
"disconnected.\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
setAxisParamChecked(axis, motorConnected, false);
status = callParamCallbacks();
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d:\nCould not update parameter library\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
return status;
if (axis != nullptr) {
setAxisParamChecked(axis, motorConnected, false);
status = callParamCallbacks();
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d:\nCould not update parameter library\n",
portName, axisNo, __PRETTY_FUNCTION__,
__LINE__);
return status;
}
}
}
break;