Following some off-line discussions with Mark, I can report the actual problem wasn't specific to the 8752 driver, but an interaction between the Prosilica AreaDetector camera driver (which my IOC was also running) and asyn which was causing the 8752 driver's asyn read call to return prematurely. Mark described the problem much more eloquently than I can:
The Prosilica library uses Posix high-precision timer library. That library uses signals that can cause Linux system functions to return
prematurely returning EINTR, so they must be restarted. Andrew Johnson fixed this problem in base some time ago when I first discovered
the problem when using Prosilica cameras.
I am pretty sure the drvAsynIPPort module has a bug. It is calling poll(), but not checking the response at all. It assumes that if poll() returned
then the port has new data. But this is incorrect, because according to the documentation poll() can return EINTR
Mark has now updated drvAsynIPPort.c in revision r2251 at https://svn.aps.anl.gov/epics/asyn/trunk/ which fixes the problem nicely, so doubtless it appear in the next asyn release also.
Many thanks to Mark for the fix, and to Eric and Kevin for their helpful suggestions.
Tim
-----Original Message-----
Date: Tue, 20 Aug 2013 19:25:19 +0000
From: Mark Rivers <[email protected]>
To: "'[email protected]'" <[email protected]>,
"[email protected]" <[email protected]>
Subject: RE: Comms issue with New Focus 8752 motor driver
It seems that sometimes when the VER command is issued the response does not arrive before the timeout expires. But then it does eventually arrive, and screws up the expected response to the DRT command. The timeout is defined on this line in the driver:
#define PMNC_TIMEOUT 3.0 /* Command timeout in sec. */
There is something I really don't understand in the output:
2013/08/20 17:37:57.709 192.168.42.31:23 write 4
VER\r
2013/08/20 17:37:57.716 192.168.42.31:23 read 1
send_recv_mess(): recv message = ""
send_recv_mess(): message = VER
2013/08/20 17:37:57.717 192.168.42.31:23 write 4
VER\r
send_recv_mess(): ERROR - staus =1, nread = 0
send_recv_mess(): message = VER
2013/08/20 17:37:57.736 192.168.42.31:23 write 4
VER\r
2013/08/20 17:37:57.742 192.168.42.31:23 read 16
Version 1.6.0\r\n>
send_recv_mess(): recv message = "Version 1.6.0
"
The line
send_recv_mess(): ERROR - staus =1, nread = 0
Is coming from this code (note the typo on status, spelled staus):
/* Perform atomic write/read operation */
status = pasynOctetSyncIO->writeRead(cntrl->pasynUser, send_com, size,
recv_com, BUFF_SIZE-1,
PMNC_TIMEOUT, &nwrite, &nread, &eomReason);
if (eos)
// Reset EOS to default
pasynOctetSyncIO->setInputEos(cntrl->pasynUser,PROMPT_EOS,strlen(PROMPT_EOS));
if (status != asynSuccess)
{
int int_status = (int) status;
Debug(3, "send_recv_mess(): ERROR - staus =%d, nread = %d\n", int_status, nread);
recv_com[0] = '\0';
return(MESS_ERR);
}
status=1 is asynTimeout. So this is saying that the writeRead operation failed with a timeout on the read, and nread=0.
But look at the timestamps above. Only 19 ms has elapsed between the second 2 "write 4" messages, but in that time the read has timed out! This does not make sense, there should be a 3 second delay in there before the read times out.
Mark