Skip to content

Commit

Permalink
Merge pull request #19 from epics-motor/issue18
Browse files Browse the repository at this point in the history
Add locks around writeReadController to prevent conficts between the poller thread and the profile move thread.
  • Loading branch information
kmpeters authored Nov 1, 2021
2 parents e9615c7 + a795252 commit e537b51
Showing 1 changed file with 60 additions and 12 deletions.
72 changes: 60 additions & 12 deletions acsMotionApp/src/SPiiPlusDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,13 @@ asynStatus SPiiPlusController::writeReadInt(std::stringstream& cmd, int* val)

std::fill(inString, inString + 256, '\0');

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output = %s\n", driverName, functionName, cmd.str().c_str());

size_t response;
lock();
asynStatus status = this->writeReadController(cmd.str().c_str(), inString, 256, &response, -1);
unlock();

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output = %s\n", driverName, functionName, cmd.str().c_str());
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: input = %s\n", driverName, functionName, inString);
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

Expand Down Expand Up @@ -397,10 +400,13 @@ asynStatus SPiiPlusController::writeReadDouble(std::stringstream& cmd, double* v

std::fill(inString, inString + 256, '\0');

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output = %s\n", driverName, functionName, cmd.str().c_str());

size_t response;
lock();
asynStatus status = this->writeReadController(cmd.str().c_str(), inString, 256, &response, -1);
unlock();

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output = %s\n", driverName, functionName, cmd.str().c_str());
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: input = %s\n", driverName, functionName, inString);
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

Expand Down Expand Up @@ -444,10 +450,13 @@ asynStatus SPiiPlusController::writeReadAck(std::stringstream& cmd)

std::fill(inString, inString + 256, '\0');

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output = %s\n", driverName, functionName, cmd.str().c_str());

size_t response;
lock();
asynStatus status = this->writeReadController(cmd.str().c_str(), inString, 256, &response, -1);
unlock();

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output = %s\n", driverName, functionName, cmd.str().c_str());
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: input = %s\n", driverName, functionName, inString);
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

Expand Down Expand Up @@ -480,6 +489,8 @@ asynStatus SPiiPlusController::writeReadBinary(char *output, int outBytes, char
asynStatus status;
static const char *functionName = "writeReadBinary";

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: start\n", driverName, functionName);

lock();

std::fill(outString_, outString_ + MAX_CONTROLLER_STRING_SIZE, '\0');
Expand All @@ -492,21 +503,26 @@ asynStatus SPiiPlusController::writeReadBinary(char *output, int outBytes, char
// Flush the receive buffer
status = pasynOctetSyncIO->flush(pasynUserController_);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: output bytes = %i, output = %s\n", driverName, functionName, outBytes, output);

// Send the query command
memcpy(outString_, output, outBytes);
status = pasynOctetSyncIO->write(pasynUserController_, outString_, outBytes, SPIIPLUS_CMD_TIMEOUT, &nwrite);

// The reply from the controller has a 4-byte header and a 1-byte suffix
status = pasynOctetSyncIO->read(pasynUserController_, packetBuffer, inBytes, SPIIPLUS_ARRAY_TIMEOUT, &nread, &eomReason);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: input bytes = %i\n", driverName, functionName, inBytes);
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

if (status == asynSuccess)
{
// Check for an error reply
status = binaryErrorCheck(packetBuffer);
if (status == asynError)
{
*sliceAvailable = false;
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: No more slices due to error\n", driverName, functionName);
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Binary read failed (controller)\n", driverName, functionName);
}
else
{
Expand All @@ -533,7 +549,7 @@ asynStatus SPiiPlusController::writeReadBinary(char *output, int outBytes, char
else
{
*sliceAvailable = false;
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: No more slices due to a failed read: status=%i, nread=%li\n", driverName, functionName, status, nread);
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Binary read failed (asyn): status=%i, nread=%li\n", driverName, functionName, status, nread);
}

// Restore the EOS characters
Expand All @@ -542,6 +558,8 @@ asynStatus SPiiPlusController::writeReadBinary(char *output, int outBytes, char

unlock();

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: end\n", driverName, functionName);

return status;
}

Expand Down Expand Up @@ -585,6 +603,8 @@ asynStatus SPiiPlusController::getDoubleArray(char *output, const char *var, int
bool sliceAvailable;
static const char *functionName = "getDoubleArray";

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: start\n", driverName, functionName);

std::fill(outString_, outString_ + MAX_CONTROLLER_STRING_SIZE, '\0');

// Create the command to query array data. This could be the only command
Expand All @@ -594,10 +614,14 @@ asynStatus SPiiPlusController::getDoubleArray(char *output, const char *var, int
remainingBytes = dataBytes;
readBytes = 0;

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: var = %s, ((%i, %i), (%i, %i))\n", driverName, functionName, var, idx1start, idx1end, idx2start, idx2end);

// Send the command
status = writeReadBinary((char*)command, outBytes, output+readBytes, inBytes, &nread, &sliceAvailable);
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Initial array query: request = %i; read = %li\n", driverName, functionName, inBytes, nread);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

remainingBytes -= nread;
readBytes += nread;

Expand All @@ -607,18 +631,20 @@ asynStatus SPiiPlusController::getDoubleArray(char *output, const char *var, int
// Create the command to query the next slice of the array data
readFloat64SliceCmd(command, slice, var, idx1start, idx1end, idx2start, idx2end, &outBytes, &inBytes, &dataBytes);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: var = %s, ((%i, %i), (%i, %i)), slice %i\n", driverName, functionName, var, idx1start, idx1end, idx2start, idx2end, slice);

// Send the command
status = writeReadBinary((char*)command, outBytes, output+readBytes, inBytes, &nread, &sliceAvailable);
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Array slice #%i query: expected = %i; read = %li; sliceAvailable = %d\n", driverName, functionName, slice, inBytes, nread, sliceAvailable);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

remainingBytes -= nread;
readBytes += nread;
slice++;
}

// Restore the EOS characters
pasynOctetSyncIO->setInputEos(pasynUserController_, "\r", 1);
pasynOctetSyncIO->setOutputEos(pasynUserController_, "\r", 1);
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: end\n", driverName, functionName);

return status;
}
Expand All @@ -635,6 +661,8 @@ asynStatus SPiiPlusController::getIntegerArray(char *output, const char *var, in
bool sliceAvailable;
static const char *functionName = "getIntegerArray";

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: start\n", driverName, functionName);

std::fill(outString_, outString_ + MAX_CONTROLLER_STRING_SIZE, '\0');

// Create the command to query array data. This could be the only command
Expand All @@ -644,10 +672,14 @@ asynStatus SPiiPlusController::getIntegerArray(char *output, const char *var, in
remainingBytes = dataBytes;
readBytes = 0;

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: var = %s, ((%i, %i), (%i, %i))\n", driverName, functionName, var, idx1start, idx1end, idx2start, idx2end);

// Send the command
status = writeReadBinary((char*)command, outBytes, output+readBytes, inBytes, &nread, &sliceAvailable);
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Initial array query: request = %i; read = %li\n", driverName, functionName, inBytes, nread);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

remainingBytes -= nread;
readBytes += nread;

Expand All @@ -657,31 +689,35 @@ asynStatus SPiiPlusController::getIntegerArray(char *output, const char *var, in
// Create the command to query the next slice of the array data
readInt32SliceCmd(command, slice, var, idx1start, idx1end, idx2start, idx2end, &outBytes, &inBytes, &dataBytes);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: var = %s, ((%i, %i), (%i, %i)), slice %i\n", driverName, functionName, var, idx1start, idx1end, idx2start, idx2end, slice);

// Send the command
status = writeReadBinary((char*)command, outBytes, output+readBytes, inBytes, &nread, &sliceAvailable);
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Array slice #%i query: expected = %i; read = %li; sliceAvailable = %d\n", driverName, functionName, slice, inBytes, nread, sliceAvailable);

asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: status = %i\n", driverName, functionName, status);

remainingBytes -= nread;
readBytes += nread;
slice++;
}

// Restore the EOS characters
pasynOctetSyncIO->setInputEos(pasynUserController_, "\r", 1);
pasynOctetSyncIO->setOutputEos(pasynUserController_, "\r", 1);
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: end\n", driverName, functionName);

return status;
}

asynStatus SPiiPlusController::poll()
{
asynStatus status;
//static const char *functionName = "poll";
static const char *functionName = "poll";

/*
* Read position and status using binary queries here and parse the replies in the axis poll method
*/

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: POLL_START\n", driverName, functionName);

status = getDoubleArray((char *)axisPosition_, "APOS", 0, numAxes_-1, 0, 0);
if (status != asynSuccess) return status;

Expand All @@ -703,6 +739,8 @@ asynStatus SPiiPlusController::poll()
status = getDoubleArray((char *)maxAcceleration_, "XACC", 0, numAxes_-1, 0, 0);
if (status != asynSuccess) return status;

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: POLL_END\n", driverName, functionName);

return status;
}

Expand Down Expand Up @@ -1721,6 +1759,8 @@ asynStatus SPiiPlusController::runProfile()
std::string posData;
static const char *functionName = "runProfile";

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: start\n", driverName, functionName);

if (profileAxes_.size() == 0)
{
strcpy(message, "No axes selected");
Expand Down Expand Up @@ -1862,6 +1902,8 @@ asynStatus SPiiPlusController::runProfile()
cmd << axesToString(profileAxes_);
status = writeReadAck(cmd);

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: point buffer fill start\n", driverName, functionName);

// Fill the point buffer, which can only hold 50 points
for (ptIdx = 0; ptIdx < MIN(50, fullProfileSize_); ptIdx++)
{
Expand All @@ -1873,6 +1915,8 @@ asynStatus SPiiPlusController::runProfile()
ptLoadedIdx++;
}

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: point buffer fill end\n", driverName, functionName);

if (fullProfileSize_ > 50)
{
// Send the GO command
Expand Down Expand Up @@ -1903,6 +1947,8 @@ asynStatus SPiiPlusController::runProfile()
// load the rest of the points as needed
for (ptIdx=ptLoadedIdx; ptIdx<(ptLoadedIdx+ptFree); ptIdx++)
{
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: sending another point\n", driverName, functionName);

// Create and send the point command (should this be ptIdx+1?)
cmd << "POINT " << axesToString(profileAxes_) << ", " << positionsToString(ptIdx) << ", " << lround(fullProfileTimes_[ptIdx] * 1000.0);
status = writeReadAck(cmd);
Expand Down Expand Up @@ -1971,6 +2017,8 @@ asynStatus SPiiPlusController::runProfile()
unlock();
}

asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: profile move is done\n", driverName, functionName);

// Confirm that the motors are done moving?

lock();
Expand Down

0 comments on commit e537b51

Please sign in to comment.