Multiple Application / Multiple Device Operation [EN]
Introduction
It is often required to address several COMSOL devices within one application or to access one COMSOL device with several applications.
This application note describes the possibilities and what to considered.
Multiple-Device
The access to several COMSOL devices by one application is no problem at all.
This is achieved by repeatedly calling the xChannelOpen function and parameterizing different board names.
The repeated call results in the generation of another channel handle; the handling of which is necessary in the further course of the application.
By selecting the handle when transferring the hChannel parameter to one of the xChannel functions, it is determined which device is addressed.
Ideally, the process data handling of the two devices as well as the handling should be decoupled from the rest of the application (multithreading, multiprocessing).
This is also recommended for single-device operation.
Practice implementation
To use multiple devices, multiple calls to the xChannelOpen function are required.
Different devices can be selected using the szBoard parameters.
The resulting handles relate to the different devices. Therefore, these should always be treated selectively in the further course of the application.
It is not necessary to open the driver multiple times via xDriverOpen.
/*****************************************************************************/ /*! Function to handle I/O-data. Using to handle the I/O data from different * devices in own threads. * Packet Transfer and I/O Data exchange * \return CIFX_NO_ERROR on success */ /*****************************************************************************/ DWORD WINAPI IODataHandler(LPVOID hChannel) { long lRet = CIFX_NO_ERROR; /* Read and write I/O data (32Bytes). Output data will be incremented each cyle */ unsigned char abRecvData[64] = { 0 }; unsigned char abSendData[64] = { 0 }; /* Do I/O Data exchange until a key is hit */ while (/* loop condition */) { if (CIFX_NO_ERROR != (lRet = xChannelIORead(hChannel, 0, 0, sizeof(abRecvData), abRecvData, IO_WAIT_TIMEOUT))) { ... } if (CIFX_NO_ERROR != (lRet = xChannelIOWrite(hChannel, 0, 0, sizeof(abRecvData), abRecvData, IO_WAIT_TIMEOUT))) { ... } ... } } /*****************************************************************************/ /*! Function to demonstrate communication channel functionality * Packet Transfer and I/O Data exchange * \return CIFX_NO_ERROR on success */ /*****************************************************************************/ long ChannelDemo(HANDLE hDriver, char* szBoard[], uint32_t ulChannel[], uint32_t channelCount) { HANDLE* hChannels; hChannels = malloc(channelCount * 4); HANDLE hChannel = NULL; long lRet = CIFX_NO_ERROR; for (uint32_t i = 0; i < channelCount; i++) { printf("---------- Communication Channel demo ----------\r\n"); lRet = xChannelOpen(hDriver, szBoard, ulChannel, &hChannel); if (CIFX_NO_ERROR != lRet) { printf("Error opening Channel!"); } else { ... ... ... /* Set Host Ready to signal the filed bus an application is ready */ lRet = xChannelHostState(hChannel, CIFX_HOST_STATE_READY, &ulState, HOSTSTATE_TIMEOUT); if (CIFX_NO_ERROR != lRet) { printf("Error setting host ready!\r\n"); } else { /* Switch on the bus if it is not automatically running (see configuration options) */ lRet = xChannelBusState(hChannel, CIFX_BUS_STATE_ON, &ulState, 0L); if (CIFX_NO_ERROR != lRet) { printf("Unable to start the filed bus!\r\n"); } else { DWORD dwThreadID = 0; hAppThreads[i] = CreateThread( NULL, 0, IODataHandler, hChannels[i], 0, &dwThreadID); } } } /* Wait for all threads terminated */ lRet = WaitForMultipleObjects(channelCount, hAppThreads, TRUE, INFINITE); /* Close all Channel-Handler */ for (uint32_t i = 0; i < channelCount; i++) { xChannelClose(ulChannel[i]); } free(hChannels); } }
The source code shown is part of the following demo application:Â cifX Demo multiple device
Multiple-Application
Whether several applications can be operated with one COMSOL device depends largely on the driver used.
In principle, several instances of the application or driver must be known to each other so that locking mechanisms for the resources used take effect.
Regardless of the operating system used, the following factors should be taken into account:
Each time the xChannelIORead or xChannelIOWrite functions are called, the handshake flags are automatically handled.
The handshaking controls access to the DPM and, depending on the protocol stack used and the operating mode set, can be synchronous with the bus cycle.
Calling the function again would in this case be a "blocking" call.
The function is only terminated and a value is returned with the next bus cycle and the toggling of the handshake.
In this case, however, the value no longer comes from the same bus cycle.
Conversely, with asynchronous operation it is completely unclear whether the values of two calls of the xChannelIORead / Write functions come from different or the same bus cycle.
The use of a data provider that handles the process data directly at the CIFX API and distributes or receives the information to the respective applications is recommended.
Windows
Using the Windows driver, the essential components of the driver are implemented in the kernel space.
The part of the driver that protects the relevant resources is therefore not started in several processes.
Therefore an operation of multiple applications that access a CIFX card, so absolutely possible.
Linux
In the standard Linux driver, the signed part of the driver is designed as a userspace module.
Each instance of the driver or an application runs in its own process. Since no interprocess communication is implemented in the driver, the protective precautions for the resources do not work across multiple driver instances.
It is therefore not possible to operate multiple applications.