Interface Equipment Links
Introduction
Equipment links define relationships between FESA classes allowing one class to access properties and data of another class. Interface equipment links are one of the three types of equipment links possible in FESA. A description and manual can be found
here. This HowTo focuses on interface equipment links and details the pitfalls not mentioned in the manual.
Interface equipment links allow one FESA class to talk to another FESA class by using the latters interface and properties the same way the common middleware and GUI does. However, as both classes must reside on the same front end computer, there is no communication via network etc. involved.
A FESA executable consists of 3 parts:
- interface part
- real time part
- data
When the FESA class is deployed as a single-process (most common option) all three parts reside in a single execuatble called
classname_M.cpu
(i.e. FCT_SIS3350_M.ppc4 for a RIO3 cpu). The interface and real time part are also compiled as libraries. Using interface equipment links requires to things:
- the calling class must have knowledge of the interface of the called class
- the data of the called class must reside in a shared memory segment for communication
The first requirement is achieved by linking the interface part library of the called class to the binary of the calling class. The second requirement means, that the called class must be deployed as seperate-server-split. Otherwise, the data segement resides in the process owned memory and not in a shared memory segment.
The image below illustrates the deployment for two classes: FCT_SIS3350 and
HBrTest with the first being called by the latter.
Note: The interface part of the called class exists twice on the front end. Thus any initialization which should occur only once like VME mapping, register mapping etc. must be done in the initialization of the real time part and not in the interface part.
Preparing the called class
Step 1
As the interface part library of the called class must be linked to the calling class, the compiler needs to have access to the header files and libraries. For this to work, the called class has to be delivered by the command:
FESA Deliver class version cpu
For example: FESA Deliver FCT_SIS3350 0 ppc4
Note: If any changes to the called class (i.e. FCT_SIS3350) are made, the class has to be delivered again. Otherwise, old libraries would be linked to the calling class.
Step 2
In order to have the data of the called class in a shared memory segment, the class needs to be deployed as seperate-server-split. This produces two binaries called
classname_S.cpu
for the interface/server part and
classname_R.cpu
for the realtime part. Currently to build these binaries do:
cd TEST; make server; make rt
Preparing the calling class
Step 1
Tell FESA that the interface of another class has to be linked. This is done by adding the appropriate equipment-links segment in the FESA class design. The image below shows this for the class FCT_SIS3350 version 0 whose interface is to be called from both the interface part and the real time part of the calling class.
The calling class can be deployed as usual as a single-process. The interface library of the called class will be automatically included.
Step 2
As described in the attached
document create a directory with the front end name under the TEST directory. Create links to the binary of the calling class and to the device data file of the called class. Instantiate the device data of the calling class in this directory.
As an example we assume the front end to be sddsc001, the calling class being named
HBrTest and the called class being named FCT_SIS3350. Then the following commands set up the correct file structure:
cd TEST; mkdir sddsc001; cd sddsc001
ln -s ../HBrTest_M.ppc4 HBrTest_M.ppc4
ln -s ../../../../FCT_SIS3350/v0/TEST/FCT_SIS3350DeviceData.xml FCT_SIS3350DeviceData.xml
cd ../..
Fesa Instantiate FCT_SIS3350 0 sddsc001 TEST/sddsc001
Setting / Getting data from the called class
Using the interface of the called class in a server or real time action requires the following steps:
- obtain a pointer to the equipment interface of the called class
- obtain a pointer to the device handled by the called class
- obtain a pointer to the property of the called class which is to be set or get
- set the property data and write the property or get the property and read the data.
The following code fragment shows this for the example of the FESA class FCT_SIS3350 acting on the device NONE-FCT_SIS3350. The calling class sets various settings of the class FCT_SIS3350 (using the property Settings) depending on the data passed to it.
AbstractEquipmentInterface *pInterface = AbstractEquipmentInterface::getEqpIntfFromClassName("FCT_SIS3350");
if (pInterface == 0)
{
throw FesaIOError("FESA_EQUIP", -1, "Equipment interface for FCT_SIS3350 not found!");
}
Property *pProperty = pInterface->getProperty("Settings");
Device *pDev = pInterface->getDevice("NONE-FCT_SIS3350");
rdaData d;
rdaData filter;
if (data.setting.get() == 0)
{
d.insert("ringbufferSampleLength12",4096L);
d.insert("ringbufferPreDelay12",2048L);
}
else if (data.setting.get() == 1)
{
d.insert("ringbufferSampleLength12",8192L);
d.insert("ringbufferPreDelay12",4096L);
}
else
{
d.insert("ringbufferSampleLength12",16376L);
d.insert("ringbufferPreDelay12",8192L);
}
pProperty->set(*pDev,"",filter,d);
Running it
To run everything do the following:
- start the server part of the called class (i.e. FCT_SIS3350_S.ppc4)
- start the real time part of the called class (i.e. FCT_SIS3350_R.ppc4)
- check that everything works
- in the directory created under the TEST directory start the calling class (i.e. HBrTest_M.ppc4 if it is a single process)
If you do not want to access the called class directly, there should be no reason to have its interface part running. The following should then also work (not tested yet):
- in the directory created under the TEST directory start the calling class (i.e. HBrTest_M.ppc4 if it is a single process). This also creates the shared memory segment and initializes the interface of the called class once.
- start the real time part of the called class (i.e. FCT_SIS3350_R.ppc4)
- check that everything works
A note on shared memory
When the processes are killed the shared memory is not relased. This can cause severe problems during the testing phase, when the classes have been changed and the shared memory structure does not reflect the class anymore. The shared memory segment has to be deleted manually.
Under
LynxOS use the command
lipcs to get a list of shared memory segments. For our example with the class FCT_SIS3350 this displays:
__mq-100664141-shm SHM rw-rw-rw- uid 0 gid 0
FCT_SIS3350EquipmentShm SHM rwxrwx--- uid 0 gid 0
/FCT_SIS3350UserEv MQ rw-rw-rw- uid 0 gid 0
/dev/mem SHM rw-r--r-- uid 0 gid 0
The segment FCT_SIS3350EquipmentShm is the shared memory segment for the FCT_SIS3350 device data. It will not be present, if the class is deployed in single-process mode. The other two entries /FCT_SIS3350UserEv and __mq-100664141-shm are present also with the single-process deployment and can be ignored. Assumption: they result from the user events used in the FESA class).
The shared memory segments can be deleted by the command
lipcrm. For example
lipcrm FCT_SIS3350EquipmentShm
deletes the shared memory segment for the device data and
lipcrm /FCT_SIS3350UserEv
will delete the two entries /FCT_SIS3350UserEv and __mq-100664141-shm.
Pitfalls
If things do not work and the code crashes with segfaults for example, check the following:
- Are you using up to date libraries of the called class ?
- Are stale shared memory segments on the front end ?
- Delete all shared memory segments with lipcrm
- Are hardware pointers initialized twice ?
- Data to be initialized one only must be initialized in the real time setup as the interface part is initialized twice
- The two classes are not communicating ?
- Make sure the called class is compiled as seperate server and RT part