EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025  2026  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025  2026 
<== Date ==> <== Thread ==>

Subject: Re: asyn port locking while motorIMS controller limit-switch configuration is read
From: Mark Rivers via Tech-talk <[email protected]>
To: Sebastian Eckert <[email protected]>
Cc: "[email protected]" <[email protected]>
Date: Fri, 1 Nov 2024 13:18:42 +0000
Hi Sebastian,

Here is a cleaner way to do it, which is actually less code.  It does not rely on knowing the private structure in the pasynUserIMS->drvUser.

   asynInterface psynInterface = pasynManager->findInterface(pasynUserIMS,asynOctetType,1);
   asynOctet *pasynOctet = pasynInterface->pinterface;
   void *octetPvt  = pasynInterface->drvPvt;

   pasynUserIMS->timeout = IMS_TIMEOUT;
   printf("Trying to lock port.\n");
   pasynManager->lockPort(pAsynUserIMS);
   sprintf(cmd, "PR IS");
   resp[0] = 0;
   printf("Prepared command and response string.\n"); 
   pasynOctet->setInputEos(octetPvt, pAsynUserIMS, "\0", 1);
   printf("Changed EOS to zero.\n");
   // in party-mode Line Feed must follow command string
   sprintf(outbuff, "%s%s", deviceName, cmd);
   printf("Writing to controller.\n");
   status = pasynOctet->write(octetPvt, pAsynUserIMS, outbuff, strlen(outbuff), &nwrite);
   status = pasynOctet->read(octetPvt, pAsynUserIMS, resp, sizeof(resp), &nread, &eomReason);
   printf("Write and read finished.\n");
   pasynOctet->setInputEos(octetPvt, pAsynUserIMS, "\n", 1);
   printf("Changed EOS to newline.\n");
   printf("%s\n", resp);
   pasynManager->unlockPort(pAsynUserIMS);

Mark


From: Sebastian Eckert <[email protected]>
Sent: Friday, November 1, 2024 7:48 AM
To: Mark Rivers <[email protected]>
Cc: [email protected] <[email protected]>
Subject: Re: asyn port locking while motorIMS controller limit-switch configuration is read
 
Hi Mark,

your way of circumventing the lock in the SyncIO functions works well. We will commit the fix to GitHub soon.
Thanks a lot!

Best regards
Sebastian

> Am 29.10.2024 um 17:52 schrieb Mark Rivers <[email protected]>:
>
> Hi Sebastian,
>  That output is what I expected.  It means the call to pasynOctetSyncIO->writeRead() in writeReadController is hanging.  That is because once you call pasynManager->lockPort() you cannot use the SyncIO functions, you must call the low-level pasynOctet functions.  I believe the solution is very similar to the tech-talk message I posted a few minutes ago:
> https://epics.anl.gov/tech-talk/2024/msg01204.php
>  I suggest you try changing your code to this (untested, probably has some typos):
>  struct octetPvt {
>    asynCommon   *pasynCommon;
>    void         *pcommonPvt;
>    asynOctet    *pasynOctet;
>    void         *octetPvt;
>    asynDrvUser  *pasynDrvUser;
>    void         *drvUserPvt;
> };
>  octetPvt *pPvt = (octetPvt *) pasynUserOctet->userPvt;
> pasynUserIMS->timeout = IMS_TIMEOUT;
>  printf("Trying to lock port.\n");
> pasynManager->lockPort(pAsynUserIMS);
> sprintf(cmd, "PR IS");
> resp[0] = 0;
> printf("Prepared command and response string.\n");
> pPvt->pasynOctet->setInputEos(pPvt->octetPvt, pAsynUserIMS, "\0", 1);
> printf("Changed EOS to zero.\n");
> // in party-mode Line Feed must follow command string
> sprintf(outbuff, "%s%s", deviceName, cmd);
> printf("Writing to controller.\n");
> status = pPvt->pasynOctet->write(pPvt->octetPvt, pAsynUserIMS, outbuff, strlen(outbuff), &nwrite);
> status = pPvt->pasynOctet->read(pPvt->octetPvt, pAsynUserIMS, resp, sizeof(resp), &nread, &eomReason);
> printf("Write and read finished.\n");
> pPvt->pasynOctet->setInputEos(pPvt->octetPvt, pAsynUserIMS, "\n", 1);
> printf("Changed EOS to newline.\n");
> printf("%s\n", resp);
> pasynManager->unlockPort(pAsynUserIMS);
>  Please try that and let me know if it works.
>  Mark
>   From: Eckert, Sebastian <[email protected]>
> Sent: Tuesday, October 29, 2024 4:09 AM
> To: Mark Rivers <[email protected]>; [email protected]
> Subject: AW: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Mark,
>  here is the output:
>  Controller version LMDCM 6.016, Hw: 2.8
> Setup config:
> Lexium MDrive detected
> -------------------------------------------
> Have device name going party modus, line ending LF.
> Trying to lock port.
> Prepared command and response string.
> Changed EOS to zero.
> Writing to controller.
>  Then the boot process is stuck.
>  Best
> SebastianVon: Mark Rivers <[email protected]>
> Gesendet: Montag, 28. Oktober 2024 18:43:47
> An: Eckert, Sebastian; [email protected]
> Betreff: RE: asyn port locking while motorIMS controller limit-switch configuration is read
>  What is the output when you run the driver?  I want to see which of the printf() statements in int ImsMDrivePlusMotorController::readHomeAndLimitConfig() are bring printed.
>  Mark
>   From: Eckert, Sebastian <[email protected]>
> Sent: Monday, October 28, 2024 9:00 AM
> To: Mark Rivers <[email protected]>; [email protected]
> Subject: AW: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Mark,
>  the first few differences are in the Axis.cpp file to see which problem occurs in the poll, then follow the differences regarding the eos.
>  Best
> Sebastian
>  diff --git a/imsApp/src/ImsMDrivePlusMotorAxis.cpp b/imsApp/src/ImsMDrivePlusMotorAxis.cpp
> index cd3e900..ae3417c 100644
> --- a/imsApp/src/ImsMDrivePlusMotorAxis.cpp
> +++ b/imsApp/src/ImsMDrivePlusMotorAxis.cpp
> @@ -41,6 +41,7 @@
>  //! @param[in] pC pointer to ImsMDrivePlusMotorController
>  //! @param[in] axisNum axis number
>  ////////////////////////////////////////////////////////
> +
>  ImsMDrivePlusMotorAxis::ImsMDrivePlusMotorAxis(ImsMDrivePlusMotorController *pC, int axisNum)
>    : asynMotorAxis(pC, axisNum), pController(pC)
>  {
> @@ -407,7 +408,7 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>         // get position
>         sprintf(cmd, "PR P");
>         status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -       if (status) goto bail;
> +       if (status) {printf("get position error\n"); goto bail;}
>         position = atof(resp);
>         // update motor record position values, just update encoder's even if not using one
>         setDoubleParam(pController->motorEncoderPosition_, position);
> @@ -416,7 +417,7 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>         // get moving flag
>         sprintf(cmd, "PR MV");
>         status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -       if (status) goto bail;
> if (status) {printf("get moving flag error\n"); goto bail;}
>         val = atoi(resp);
>         *moving = val;
>         setIntegerParam(pController->motorStatusDone_, val == 0);
> @@ -424,14 +425,14 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>                 sprintf(cmd, "R1=1");
>                 homing = false;
>                 status  = pController->writeController(cmd, IMS_TIMEOUT);
> -               if(status) goto bail;
>        if (status) {printf("get moving flag homing error\n"); goto bail;}
>         }
>
>         // get home switch value
>         if (pController->homeSwitchInput != -1) {
>                 sprintf(cmd, "PR I%d", pController->homeSwitchInput);
>                 status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -               if (status) goto bail;
>        if (status) {printf("get home switch value error\n"); goto bail;}
>                 val = atoi(resp);
>                 setIntegerParam(pController->motorStatusHome_, val);
>         }
> @@ -440,7 +441,7 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>         if (pController->posLimitSwitchInput != -1) {
>                 sprintf(cmd, "PR I%d", pController->posLimitSwitchInput);
>                 status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -               if (status) goto bail;
>        if (status) {printf("get positive limit switch value error\n"); goto bail;}
>                 val = atoi(resp);
>                 setIntegerParam(pController->motorStatusHighLimit_, val);
>         }
> @@ -449,7 +450,7 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>         if (pController->negLimitSwitchInput != -1) {
>                 sprintf(cmd, "PR I%d", pController->negLimitSwitchInput);
>                 status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -               if (status) goto bail;
>        if (status) {printf("get negative limit switch value error\n"); goto bail;}
>                 val = atoi(resp);
>                 setIntegerParam(pController->motorStatusLowLimit_, val);
>         }
> @@ -457,14 +458,14 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>         // Read isHomed status
>         sprintf(cmd, "PR R1");
>         status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -       if (status) goto bail;
> +       if (status) {printf("read isHomed status error\n"); goto bail;}
>         val = atoi(resp);
>         setIntegerParam(pController->motorStatusHomed_, val > 0);
>
>         // Read stall flag
>         sprintf(cmd, "PR ST");
>         status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -       if (status) goto bail;
> +       if (status) {printf("read stall flag error\n"); goto bail;}
>         val = atoi(resp);
>         setIntegerParam(pController->motorStatusFollowingError_, val > 0);
>         setIntegerParam(pController->motorStatusSlip_, val > 0);
> @@ -472,7 +473,7 @@ asynStatus ImsMDrivePlusMotorAxis::poll(bool *moving)
>         // Read encoder counts
>         sprintf(cmd, "PR C2");
>         status = pController->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> -       if (status) goto bail;
> +       if (status) {printf("read encoder counts error\n"); goto bail;}
>         val = atoi(resp);
>         setDoubleParam(pController->motorEncoderPosition_, val);
>
> diff --git a/imsApp/src/ImsMDrivePlusMotorController.cpp b/imsApp/src/ImsMDrivePlusMotorController.cpp
> index c8e3112..a9da23e 100644
> --- a/imsApp/src/ImsMDrivePlusMotorController.cpp
> +++ b/imsApp/src/ImsMDrivePlusMotorController.cpp
> @@ -185,7 +185,17 @@ int ImsMDrivePlusMotorController::readHomeAndLimitConfig()
>                 // LMD motor - different terminating characters
>                 printf("Lexium MDrive detected\n");
>                 printf("-------------------------------------------\n");
> -               pasynOctetSyncIO->setOutputEos(pAsynUserIMS, "\r", 1);
>         //if (strcmp(this->deviceName, ""))
>         if (this->deviceName[0]=='\0')
>         {
>                 printf("Have no device name, line ending CR.\n");
>                 pasynOctetSyncIO->setOutputEos(pAsynUserIMS, "\r", 1);
>         }
>         else
>         {
>                 printf("Have device name going party modus, line ending LF.\n");
>                 pasynOctetSyncIO->setOutputEos(pAsynUserIMS, "\n", 1);
>         }
>         }
>         else
>         {
> @@ -205,12 +215,20 @@ int ImsMDrivePlusMotorController::readHomeAndLimitConfig()
>         }
>
>         // Any Lexium from here on
> -       pasynOctetSyncIO->setInputEos(pAsynUserIMS, "\0", 1);
> -       sprintf(cmd, "PR IS");
> -       resp[0] = 0;
> //this->lock();
> printf("Trying to lock port.\n");
> pasynManager->lockPort(pAsynUserIMS);
> sprintf(cmd, "PR IS");
> resp[0] = 0;
> printf("Prepared command and response string.\n");
> pasynOctetSyncIO->setInputEos(pAsynUserIMS, "\0", 1);
> printf("Changed EOS to zero.\n");
>         status = this->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> printf("Executed writeReadController.\n");
> pasynOctetSyncIO->setInputEos(pAsynUserIMS, "\n", 1);
> printf("Changed EOS to newline.\n");
>         printf("%s\n", resp);
> -       pasynOctetSyncIO->setInputEos(pAsynUserIMS, "\n", 1);
> pasynManager->unlockPort(pAsynUserIMS);
>         // quick and dirty solution:
>         // kill all nondigit chars, break into separate strings on LF, scan 3 params
>         if (nread > 0) {
> @@ -359,7 +377,9 @@ asynStatus ImsMDrivePlusMotorController::writeReadController(const char *output,
>
>         // in party-mode Line Feed must follow command string
>         sprintf(outbuff, "%s%s", deviceName, output);
> printf("Writing to controller.\n");
>         status = pasynOctetSyncIO->writeRead(pAsynUserIMS, outbuff, strlen(outbuff), input, maxChars, timeout, &nwrite, nread, &eomReason);
> printf("Writing finished.\n");
>         if (status) { // update comm flag
>                 setIntegerParam(this->motorStatusCommsError_, 1);
>         }
>  Von: Mark Rivers <[email protected]>
> Gesendet: Montag, 28. Oktober 2024 13:47:56
> An: Eckert, Sebastian; [email protected]
> Betreff: Re: asyn port locking while motorIMS controller limit-switch configuration is read
>  Can you send a "git diff" of your modified driver from the master branch on Github?
>  Mark
>  From: Eckert, Sebastian <[email protected]>
> Sent: Monday, October 28, 2024 5:47 AM
> To: Mark Rivers <[email protected]>; [email protected] <[email protected]>
> Subject: AW: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Mark,
>  if I use pasynManager->lockPort(pAsynUserIMS) the boot is stuck at the call in line 211:
>  status = this->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
>  and therein in line 362:
> status = pasynOctetSyncIO->writeRead(pAsynUserIMS, outbuff, strlen(outbuff), input, maxChars, timeout, &nwrite, nread, &eomReason);
>  Can it be that we interfere with the queueLockPort in the asyn writeRead function?
>  Best
> Sebastian
>  Von: Mark Rivers <[email protected]>
> Gesendet: Mittwoch, 23. Oktober 2024 19:31:16
> An: Eckert, Sebastian; [email protected]
> Betreff: RE: asyn port locking while motorIMS controller limit-switch configuration is read
>  I was mistaken, I just looked at the driver and pasynUserIMS is the correct asynUser.  This is where it is connected to the underlying IOPortName driver.
https://github.com/epics-motor/motorIms/blob/f1abd73f1971810c16b580c1f0e328ccb656badf/imsApp/src/ImsMDrivePlusMotorController.cpp#L68
>
>     • Using pasynManager->lockPort(pAsynUserIMS) prevents any further controller configuration and the IOC hangs at the boot process.
>  Once you lock the port you probably cannot used the SyncIO functions, you need to use the non-SyncIO versions.  You should put printf statements for each line after you lock the port and see where it is hanging.
>  Mark
>   From: Eckert, Sebastian <[email protected]>
> Sent: Wednesday, October 23, 2024 11:52 AM
> To: Mark Rivers <[email protected]>; [email protected]
> Subject: AW: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Mark,
>  would this be pasynUserSelf or how do I pass the correct user?
>  Best,
> SebastianVon: Mark Rivers <[email protected]>
> Gesendet: Mittwoch, 23. Oktober 2024 18:20:57
> An: Eckert, Sebastian; [email protected]
> Betreff: RE: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Sebastian,
>  You are using the wrong pasynUser.  You need to use the pasynUser that is connected to the RS-485 asyn port driver, not to the IMS port driver.
>  Mark
>   From: Eckert, Sebastian <[email protected]>
> Sent: Wednesday, October 23, 2024 11:16 AM
> To: Mark Rivers <[email protected]>; [email protected]
> Subject: AW: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Mark,
>  Thanks for the help!
>  Using pasynManager->lockPort(pAsynUserIMS) prevents any further controller configuration and the IOC hangs at the boot process.
>  Using pasynManager->queueLockPort(pAsynUserIMS) I get the following error:
>  ims: pthread_mutex_lock.c:423: __pthread_mutex_lock_full: Assertion `e != EDEADLK || (kind != PTHREAD_MUTEX_ERRORCHECK_NP && kind != PTHREAD_MUTEX_RECURSIVE_NP)' failed.
>  Best,
> SebastianVon: Mark Rivers <[email protected]>
> Gesendet: Mittwoch, 23. Oktober 2024 18:00:54
> An: Eckert, Sebastian; [email protected]
> Betreff: RE: asyn port locking while motorIMS controller limit-switch configuration is read
>  Hi Sebastian,
>  You need to lock the underlying RS-485 driver, not the IMS motor driver.  You can call pasynManager->lockPort() or pasynManager->queueLockPort()
>  Mark
>   From: Tech-talk <[email protected]> On Behalf Of Eckert, Sebastian via Tech-talk
> Sent: Wednesday, October 23, 2024 10:50 AM
> To: [email protected]
> Subject: asyn port locking while motorIMS controller limit-switch configuration is read
>  Dear asyn and motor-record experts,
>  I have trouble with the lines 208 to 213 in the following file of the motorIMS driver:
https://github.com/epics-motor/motorIms/blob/master/imsApp/src/ImsMDrivePlusMotorController.cpp#L208
>  pasynOctetSyncIO->setInputEos(pAsynUserIMS, "\0", 1);
> sprintf(cmd, "PR IS");
> resp[0] = 0;
> status = this->writeReadController(cmd, resp, sizeof(resp), &nread, IMS_TIMEOUT);
> printf("%s\n", resp);
> pasynOctetSyncIO->setInputEos(pAsynUserIMS, "\n", 1);
>  There the inputEOS is changed, because the controller's response to the "PR IS" contains information on the limit-switch configuration in multiple lines each teminated with \n. If one doesn't change the EOS, only the configuration of the first analog input is read and info on the others is lost.
>  This works fine as long as there is just one motor controller on the RS-485 line. When multiple controllers are used, the change of the eos for the controller which is created interferes with the poll-routines of the other motors, which are already set-up. I tried to lock the port during this step of the configuration with this->lock() before and this->unlock() after the mentioned lines of code, but it had no effect. Is there a way to lock the port, or to pause the polling of the other controllers while the mentioned lines are executed.
>  Thanks a lot in advance!
> Sebastian
>



________________________________

Helmholtz-Zentrum Berlin für Materialien und Energie GmbH

Mitglied der Hermann von Helmholtz-Gemeinschaft Deutscher Forschungszentren e.V.

Aufsichtsrat: Vorsitzender Dr. Volkmar Dietz, stv. Vorsitzende Dr. Jutta Koch-Unterseher
Geschäftsführung: Prof. Dr. Bernd Rech, Thomas Frederking

Sitz Berlin, AG Charlottenburg, 89 HRB 5583

Postadresse:
Hahn-Meitner-Platz 1
14109 Berlin
Deutschland

Diese E-Mail kann vertrauliche und/oder rechtlich geschützte Informationen enthalten. Wenn Sie diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den*die Absender*in und vernichten Sie diese Mail. Das unerlaubte Kopieren, die Veröffentlichung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
This email may contain confidential and/or proprietary information. If you have received this e-mail in error, please inform the sender immediately and destroy this e-mail. Unauthorized copying, publishing or distribution of this e-mail is not permitted.

References:
asyn port locking while motorIMS controller limit-switch configuration is read Eckert, Sebastian via Tech-talk
RE: asyn port locking while motorIMS controller limit-switch configuration is read Mark Rivers via Tech-talk
AW: asyn port locking while motorIMS controller limit-switch configuration is read Eckert, Sebastian via Tech-talk
RE: asyn port locking while motorIMS controller limit-switch configuration is read Mark Rivers via Tech-talk
AW: asyn port locking while motorIMS controller limit-switch configuration is read Eckert, Sebastian via Tech-talk
RE: asyn port locking while motorIMS controller limit-switch configuration is read Mark Rivers via Tech-talk
AW: asyn port locking while motorIMS controller limit-switch configuration is read Eckert, Sebastian via Tech-talk
Re: asyn port locking while motorIMS controller limit-switch configuration is read Mark Rivers via Tech-talk
AW: asyn port locking while motorIMS controller limit-switch configuration is read Eckert, Sebastian via Tech-talk
RE: asyn port locking while motorIMS controller limit-switch configuration is read Mark Rivers via Tech-talk
AW: asyn port locking while motorIMS controller limit-switch configuration is read Eckert, Sebastian via Tech-talk
RE: asyn port locking while motorIMS controller limit-switch configuration is read Mark Rivers via Tech-talk
Re: asyn port locking while motorIMS controller limit-switch configuration is read Sebastian Eckert via Tech-talk

Navigate by Date:
Prev: IOC Shell Persist history: ERROR Permission denied (13) writing '.iocsh_history' Webb, Brad via Tech-talk
Next: Re: Procserv execute error Hu, Yong via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025  2026 
Navigate by Thread:
Prev: Re: asyn port locking while motorIMS controller limit-switch configuration is read Sebastian Eckert via Tech-talk
Next: Review of submission for new QuadEM Iain Marcuson via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025  2026 
ANJ, 19 Mar 2026 · Home · News · About · Talk · Base · Modules · Extensions ·
· Distributions · Download · Documents · Links · Licensing ·