Added new feature msgPrintControl from sinqMotor 0.8.0. Correspondingly,

the minimum version requirement for sinqMotor has been bumped to 0.8.0.
This commit is contained in:
2025-03-04 09:29:19 +01:00
parent 8f597550fa
commit dfb55a1b76
5 changed files with 261 additions and 203 deletions

View File

@ -14,7 +14,7 @@ REQUIRED+=sinqMotor
motorBase_VERSION=7.2.2
# Specify the version of sinqMotor we want to build against
sinqMotor_VERSION=mathis_s
sinqMotor_VERSION=0.8.0
# These headers allow to depend on this library for derived drivers.
HEADERS += src/turboPmacAxis.h

View File

@ -35,7 +35,8 @@ static void epicsInithookFunction(initHookState iState) {
}
}
turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo)
turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
bool initialize)
: sinqAxis(pC, axisNo), pC_(pC) {
asynStatus status = asynSuccess;
@ -63,13 +64,17 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo)
exit(-1);
}
// Register the hook function during construction of the first axis object
if (axes.empty()) {
initHookRegister(&epicsInithookFunction);
}
if (initialize) {
// Register the hook function during construction of the first axis
// object
if (axes.empty()) {
initHookRegister(&epicsInithookFunction);
}
// Collect all axes into this list which will be used in the hook function
axes.push_back(this);
// Collect all axes into this list which will be used in the hook
// function
axes.push_back(this);
}
// Initialize all member variables
waitForHandshake_ = false;
@ -360,39 +365,43 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
__PRETTY_FUNCTION__, __LINE__);
}
// Intepret the status
// Create the unique callsite identifier manually so it can be used later in
// the shouldBePrinted calls.
msgPrintControlKey keyStatus = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
bool resetCountStatus = true;
// Interpret the status
switch (axStatus) {
case -6:
// Axis is stopping
*moving = true;
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nAxis is stopping\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
break;
case -5:
// Axis is deactivated
*moving = false;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
"deactivated\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status = setStringParam(pC_->motorMessageText_, "Deactivated");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
break;
case -4:
// Emergency stop
*moving = false;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nEmergency stop "
"activated\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true,
pC_->pasynUserSelf)) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nEmergency stop "
"activated.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
resetCountStatus = false;
pl_status = setStringParam(pC_->motorMessageText_, "Emergency stop");
if (pl_status != asynSuccess) {
@ -403,13 +412,9 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
break;
case -3:
// Disabled
*moving = false;
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nAxis %d is disabled\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_);
pl_status = setStringParam(pC_->motorMessageText_, "Disabled");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
@ -419,43 +424,24 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
break;
case 0:
// Idle
*moving = false;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nAxis is idle\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
break;
case 1:
// Move order acknowledged
*moving = true;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nMove order "
"acknowledged\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
break;
case 2:
// Move order confirmed possible
*moving = true;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nMove order is "
"possible\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
break;
case 3:
// Axis in Air Cushion Output status
*moving = true;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nAxis in Air "
"Cushion Output status\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
break;
case 4:
// Axis in Air Cushion Input status
*moving = true;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nAxis in Air "
"Cushion Input status\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
break;
case 5:
*moving = true;
@ -469,12 +455,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
default:
*moving = false;
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nReached unreachable "
"state P%2.2d00 = %d\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
axStatus);
if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nReached "
"unreachable state P%2.2d00 = %d.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axisNo_, axStatus, pC_->msgPrintControl_.getSuffix());
}
resetCountStatus = false;
snprintf(userMessage, sizeof(userMessage),
"Unknown state P%2.2d00 = %d has been reached. Please call "
"the support.",
@ -487,6 +478,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
}
}
if (resetCountStatus) {
pC_->msgPrintControl_.resetCount(keyStatus);
}
if (*moving) {
// If the axis is moving, evaluate the movement direction
if ((currentPosition - previousPosition) > 0) {
@ -496,19 +491,30 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
}
}
// Error handling
// Create the unique callsite identifier manually so it can be used later in
// the shouldBePrinted calls.
msgPrintControlKey keyError = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
bool resetError = true;
switch (error) {
case 0:
// No error
// No error -> Reset the message repetition watchdog
pC_->msgPrintControl_.shouldBePrinted(keyError, false,
pC_->pasynUserSelf);
break;
case 1:
// EPICS should already prevent this issue in the first place,
// since it contains the user limits
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nTarget position would "
"exceed user limits.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nTarget "
"position would exceed user limits.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
resetError = false;
pl_status = setStringParam(pC_->motorMessageText_,
"Target position would exceed software "
@ -523,11 +529,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
break;
case 5:
// Command not possible
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
"still moving, but received another move command. EPICS "
"should prevent this, check if *moving is set correctly.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true,
pC_->pasynUserSelf)) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
"still moving, but received another move command. EPICS "
"should prevent this, check if *moving is set correctly.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
resetError = false;
pl_status = setStringParam(pC_->motorMessageText_,
"Axis received move command while it is "
@ -541,12 +553,15 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
poll_status = asynError;
break;
case 8:
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAir cushion feedback "
"stopped during movement (P%2.2d01 = %d).\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
error);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAir cushion "
"feedback stopped during movement (P%2.2d01 = %d).%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axisNo_, error, pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(userMessage, sizeof(userMessage),
"Air cushion feedback stopped during movement (P%2.2d01 = "
@ -561,11 +576,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
}
break;
case 9:
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nNo air cushion "
"feedback before movement start (P%2.2d01 = %d).\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axisNo_, error);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nNo air cushion "
"feedback before movement start (P%2.2d01 = %d).%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
error, pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(userMessage, sizeof(userMessage),
"No air cushion feedback before movement start (P%2.2d01 = "
@ -585,10 +605,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
error case can only happen if either the axis has an incremental encoder
which is not properly homed or if a bug occured.
*/
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis hit the "
"controller limits.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis hit the "
"controller limits.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(userMessage, sizeof(userMessage),
"Software limits or end switch hit (P%2.2d01 = %d). Try "
@ -608,10 +635,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
break;
case 11:
// Following error
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
"following error exceeded.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
"following error exceeded.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(command, sizeof(command),
"Maximum allowed following error exceeded (P%2.2d01 = %d). "
@ -629,6 +663,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
break;
case 12:
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nSecurity "
"input is triggered (P%2.2d01 = %d).%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axisNo_, error, pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(command, sizeof(command),
"Security input is triggered (P%2.2d01 = %d). Check the SPS "
"for errors (if available). Otherwise please call "
@ -646,11 +690,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
case 13:
// Driver hardware error triggered
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nDriver hardware error "
"triggered.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nDriver "
"hardware error triggered.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(command, sizeof(command),
"Driver hardware error (P%2.2d01 = 13). "
"Please call the support.",
@ -667,12 +717,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
case 14:
// EPICS should already prevent this issue in the first place,
// since it contains the user limits
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nMove command exceeds "
"hardware limits (P%2.2d01 = %d).\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
error);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nMove "
"command exceeds hardware limits (P%2.2d01 = %d).%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axisNo_, error, pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(userMessage, sizeof(userMessage),
"Move command exceeds hardware limits (P%2.2d01 = %d). Please "
@ -688,11 +742,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
poll_status = asynError;
break;
default:
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nUnknown error "
"P%2.2d01 = %d.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axisNo_, error);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nUnknown error "
"P%2.2d01 = %d.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
error, pC_->msgPrintControl_.getSuffix());
}
resetError = false;
snprintf(userMessage, sizeof(userMessage),
"Unknown error P%2.2d01 = %d. Please call the support.",
@ -708,6 +768,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
break;
}
if (resetError) {
pC_->msgPrintControl_.resetCount(keyError);
}
// Update the parameter library
if (error != 0) {
pl_status = setIntegerParam(pC_->motorStatusProblem_, true);

View File

@ -15,7 +15,8 @@ class turboPmacAxis : public sinqAxis {
* @param pController Pointer to the associated controller
* @param axisNo Index of the axis
*/
turboPmacAxis(turboPmacController *pController, int axisNo);
turboPmacAxis(turboPmacController *pController, int axisNo,
bool initialize = true);
/**
* @brief Destroy the turboPmacAxis

View File

@ -133,39 +133,18 @@ Access one of the axes of the controller via the axis adress stored in asynUser.
If the axis does not exist or is not a Axis, a nullptr is returned and an
error is emitted.
*/
turboPmacAxis *turboPmacController::getAxis(asynUser *pasynUser) {
turboPmacAxis *turboPmacController::getTurboPmacAxis(asynUser *pasynUser) {
asynMotorAxis *asynAxis = asynMotorController::getAxis(pasynUser);
return turboPmacController::castToAxis(asynAxis);
return dynamic_cast<turboPmacAxis *>(asynAxis);
}
/*
Access one of the axes of the controller via the axis index.
If the axis does not exist or is not a Axis, the function must return Null
*/
turboPmacAxis *turboPmacController::getAxis(int axisNo) {
turboPmacAxis *turboPmacController::getTurboPmacAxis(int axisNo) {
asynMotorAxis *asynAxis = asynMotorController::getAxis(axisNo);
return turboPmacController::castToAxis(asynAxis);
}
turboPmacAxis *turboPmacController::castToAxis(asynMotorAxis *asynAxis) {
// =========================================================================
// If the axis slot of the pAxes_ array is empty, a nullptr must be returned
if (asynAxis == nullptr) {
return nullptr;
}
// Here, an error is emitted since asyn_axis is not a nullptr but also not
// an instance of Axis
turboPmacAxis *axis = dynamic_cast<turboPmacAxis *>(asynAxis);
if (axis == nullptr) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
"an instance of turboPmacAxis",
portName, axis->axisNo_, __PRETTY_FUNCTION__, __LINE__);
}
return axis;
return dynamic_cast<turboPmacAxis *>(asynAxis);
}
asynStatus turboPmacController::writeRead(int axisNo, const char *command,
@ -204,7 +183,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
// =========================================================================
turboPmacAxis *axis = getAxis(axisNo);
turboPmacAxis *axis = getTurboPmacAxis(axisNo);
if (axis == nullptr) {
// We already did the error logging directly in getAxis
return asynError;
@ -261,10 +240,6 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
// +1 for the carriage return.
const size_t fullComandLength = offset + commandLength + 1;
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
"Controller \"%s\", axis %d => %s, line %d\nSending command %s",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, fullCommand);
/*
We use separated write and read commands here, not the combined writeRead
method, because the latter is actually a flushWriteRead (see
@ -282,12 +257,19 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
status = pasynOctetSyncIO->write(lowLevelPortUser_, fullCommand,
fullComandLength, comTimeout_, &nbytesOut);
msgPrintControlKey writeKey =
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
if (status == asynTimeout) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
"writing to the MCU\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
if (msgPrintControl_.shouldBePrinted(writeKey, true, pasynUserSelf)) {
asynPrint(
this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
"writing to the MCU.%s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
msgPrintControl_.getSuffix());
}
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
sizeof(drvMessageText));
@ -309,23 +291,35 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
}
}
} else if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
"writing to the controller\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
if (msgPrintControl_.shouldBePrinted(writeKey, true, pasynUserSelf)) {
asynPrint(
this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
"writing to the controller.%s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
}
} else {
msgPrintControl_.resetCount(writeKey);
}
// Read the response from the MCU buffer
status = pasynOctetSyncIO->read(lowLevelPortUser_, response, MAXBUF_,
comTimeout_, &nbytesIn, &eomReason);
msgPrintControlKey readKey =
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
if (status == asynTimeout) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
"reading from the MCU\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
if (msgPrintControl_.shouldBePrinted(readKey, true, pasynUserSelf)) {
asynPrint(
this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
"reading from the MCU.%s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
msgPrintControl_.getSuffix());
}
// Add this event to the back of the timeout event counter
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
@ -348,11 +342,16 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
}
}
} else if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
"reading from the controller\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
if (msgPrintControl_.shouldBePrinted(readKey, true, pasynUserSelf)) {
asynPrint(
this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
"reading from the controller.%s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
}
} else {
msgPrintControl_.resetCount(readKey);
}
if (timeoutStatus == asynError) {
@ -360,6 +359,8 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
}
// The message should only ever terminate due to reason 2
msgPrintControlKey terminateKey =
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
if (eomReason != 2) {
status = asynError;
@ -367,10 +368,16 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
"Terminated message due to reason %d (should be 2).",
eomReason);
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
"Controller \"%s\", axis %d => %s, line %d\nMessage "
"terminated due to reason %i\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, eomReason);
if (msgPrintControl_.shouldBePrinted(terminateKey, true,
pasynUserSelf)) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nMessage "
"terminated due to reason %i.%s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
eomReason, msgPrintControl_.getSuffix());
}
} else {
msgPrintControl_.resetCount(terminateKey);
}
/*
@ -382,20 +389,30 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
numReceivedResponses++;
}
}
msgPrintControlKey numResponsesKey =
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
if (numExpectedResponses != numReceivedResponses) {
adjustResponseForPrint(modResponse, response, MAXBUF_);
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
"response '%s' (carriage returns are replaced with spaces) "
"for command %s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
command);
if (msgPrintControl_.shouldBePrinted(numResponsesKey, true,
pasynUserSelf)) {
asynPrint(
this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
"response '%s' (carriage returns are replaced with spaces) "
"for command %s.%s\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
command, msgPrintControl_.getSuffix());
}
snprintf(drvMessageText, sizeof(drvMessageText),
"Received unexpected response '%s' (carriage returns "
"are replaced with spaces) for command %s. "
"Please call the support",
modResponse, command);
status = asynError;
} else {
msgPrintControl_.resetCount(numResponsesKey);
}
// Create custom error messages for different failure modes, if no error
@ -425,23 +442,12 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
// Log the overall status (communication successfull or not)
if (status == asynSuccess) {
asynPrint(lowLevelPortUser_, ASYN_TRACEIO_DRIVER,
"Controller \"%s\", axis %d => %s, line %d\nDevice "
"response: %s (carriage returns are replaced with spaces)\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse);
paramLibStatus = axis->setIntegerParam(this->motorStatusCommsError_, 0);
} else {
asynPrint(lowLevelPortUser_, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nCommunication "
"failed for command %s (%s)\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, fullCommand,
stringifyAsynStatus(status));
// 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
// 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
paramLibStatus =
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
if (paramLibStatus != asynSuccess) {
@ -482,11 +488,7 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser,
// =====================================================================
turboPmacAxis *axis = getAxis(pasynUser);
if (axis == nullptr) {
// We already did the error logging directly in getAxis
return asynError;
}
turboPmacAxis *axis = getTurboPmacAxis(pasynUser);
// Handle custom PVs
if (function == rereadEncoderPosition_) {
@ -538,8 +540,8 @@ asynStatus turboPmacCreateController(const char *portName,
https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorController.cpp
https://github.com/epics-modules/asyn/blob/master/asyn/asynPortDriver/asynPortDriver.cpp
The created object is registered in EPICS in its constructor and can safely
be "leaked" here.
The created object is registered in EPICS in its constructor and can
safely be "leaked" here.
*/
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-variable"
@ -578,8 +580,8 @@ static void configTurboPmacCreateControllerCallFunc(const iocshArgBuf *args) {
args[3].dval, args[4].dval, args[5].dval);
}
// This function is made known to EPICS in turboPmac.dbd and is called by EPICS
// in order to register both functions in the IOC shell
// This function is made known to EPICS in turboPmac.dbd and is called by
// EPICS in order to register both functions in the IOC shell
static void turboPmacControllerRegister(void) {
iocshRegister(&configTurboPmacCreateController,
configTurboPmacCreateControllerCallFunc);

View File

@ -40,7 +40,7 @@ class turboPmacController : public sinqController {
* @return turboPmacAxis* If no axis could be found, this is a
* nullptr
*/
turboPmacAxis *getAxis(asynUser *pasynUser);
turboPmacAxis *getTurboPmacAxis(asynUser *pasynUser);
/**
* @brief Get the axis object
@ -49,18 +49,18 @@ class turboPmacController : public sinqController {
* @return turboPmacAxis* If no axis could be found, this is a
* nullptr
*/
turboPmacAxis *getAxis(int axisNo);
turboPmacAxis *getTurboPmacAxis(int axisNo);
/**
* @brief Overloaded function of sinqController
*
* The function is overloaded in order to read motorCanDisable_
* The function is overloaded in order to read motorCanDisable_.
*
* @param pasynUser
* @param value
* @return asynStatus
*/
asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
/**
* @brief Overloaded function of sinqController
@ -71,7 +71,7 @@ class turboPmacController : public sinqController {
* @param value New value
* @return asynStatus
*/
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
protected:
asynUser *lowLevelPortUser_;
@ -95,15 +95,6 @@ class turboPmacController : public sinqController {
asynStatus writeRead(int axisNo, const char *command, char *response,
int numExpectedResponses);
/**
* @brief Save cast of the given asynAxis pointer to a turboPmacAxis
* pointer. If the cast fails, this function returns a nullptr.
*
* @param asynAxis
* @return turboPmacAxis*
*/
turboPmacAxis *castToAxis(asynMotorAxis *asynAxis);
/**
* @brief Specialized version of sinqController::errMsgCouldNotParseResponse
* for turboPmac