Hilscher Gesellschaft für Systemautomation mbH
As some problems seems to exist (basically because the included sample is a Windows example) on how to use the cifX Toolkit.
Basics:
There are two different types of devices being handled:
Here is a short step-by-step guide, what needs to be done:
Options:
1)
When not using cifX PCI cards, or any other RAM-based device with the netX directly connected to the PCI bus, you can stub out the functions OS_ReadPCIConfig / OS_WritePCIConfig
2)
When not using Interrupts you can stub out the OS_CreateEvent, OS_SetEvent, OS_ResetEvent, OS_DeleteEvent, OS_WaitEvent functions
3)
If you don't have a multitasking environment you can stub out the Mutex functions (OS_CreateMutex, OS_WaitMutex, OS_ReleaseMutex, OS_DeleteMutex), as the mutexes are only used to prevent reentrant function calls.
Note: As the Mutexes are expected to work as the toolkit does not know about your O/S you will need to return a value != 0 out of OS_CreateMutex and OS_WaitMutex.
Attention: Doing this in a multitasking environment will result in undefined behaviour as function reentrancy cannot be controlled.
4)
If you only have a comX or another netX with flashed firmware you may stub out the file functions (OS_FileOpen, OS_FileRead, OS_FileClose) too, if you don't want to use the automatic update feature of the toolkit, which checks and updates the Firmware during startup.
Attention: When using RAM-based devices these functions must be implemented.
Options:
1)
If you only have a comX or another netX with flashed firmware you may
stub out the firmware / bootloader functions (USER_GetFirmwareFileCount, USER_GetFirmwareFile, USER_GetConfigurationFileCount, USER_GetConfigurationFile, USER_GetOSFile, USER_GetBootloaderFile), if you don't want to use the automatic update feature of the
toolkit, which checks and updates the Firmware during startup.
Attention: When using RAM-based devices these functions must be implemented.
1. allocating a DEVICE_INSTANCE structure
2. Filling in all needed parameters into this structure.
Note1: You can use the element pvOSDependent to store any non-toolkit parameters for this device.
Note2: You can override the type of the device by adjusting the element "eDeviceType" if it is not correctly auto-detected by the toolkit.
COMX Example:
OS_Memset(ptDevInstance, 0, sizeof(*ptDevInstance));
ptDevInstance->fPCICard = 0;
ptDevInstance->pbDPM = <Insert pointer to DPM here>;
ptDevInstance->ulDPMSize = <Insert accessible size of DPM here>;
OS_Strncpy(ptDevInstance->szName, "cifX0", sizeof(ptDevInstance->szName));
ptDevInstance->pvOSDependent = MyDeviceData;
cifX Example:
OS_Memset(ptDevInstance, 0, sizeof(*ptDevInstance));
ptDevInstance->fPCICard = 1;
ptDevInstance->pbDPM = <Insert pointer to DPM here>;
ptDevInstance->ulDPMSize = <Insert accessible size of DPM here>;
OS_Strncpy(ptDevInstance->szName, "cifX0", sizeof(ptDevInstance->szName));
ptDevInstance->pvOSDependent = MyDeviceData;
3. Call cifXTKitAddDevice() to add them under Toolkit control
To use DMA you will need to do the following
- Insert the preprocessor define "CIFX_TOOLKIT_DMA"
- pass 8 DMA buffers which need to be aligned on a 256 byte boundary. These buffers must be a multiple of 256 Bytes in size with a maximum size of 63.75kB
Example:
ptDevInstance->ulDMABufferCount = 8;
ptDevInstance->atDmaBuffers[0].ulSize = 8192;
ptDevInstance->atDmaBuffers[0].ulPhysicalAddress = <Insert phys. address here>;
ptDevInstance->atDmaBuffers[0].pvBuffer = <Insert virtual / cpu accessible pointer here>;
ptDevInstance->atDmaBuffers[0].pvUser = MyDMAData;
...
ptDevInstance->atDmaBuffers[7].ulSize = 8192;
ptDevInstance->atDmaBuffers[7].ulPhysicalAddress = <Insert phys. address here>;
ptDevInstance->atDmaBuffers[7].pvBuffer = <Insert virtual / cpu accessible pointer here>;
ptDevInstance->atDmaBuffers[7].pvUser = MyDMAData;
Hope this clears up some misunderstandings a little.
Regards,
MT
Hilscher Gesellschaft für Systemautomation mbH
First of all I think I need to clarify some misunderstandings of using the Toolkit. The Windows Sample included with the Toolkit is NOT meant for productional environment and is only included for showing how the toolkit works to write own drivers. Under Windows the Toolkit is already included in the Kernel-Mode Driver "cifxdrv.sys". The dll "cifx32dll.dll" just wraps the interface to this kernel mode driver.
Using the Toolkit in an application by passing the DPM pointer AND having the cifXDrv.Sys active at the same time may cause inpredictable results.
I have a realtime application (part of a control system) running in kernel mode. This application works as an EtherCAT slave and exchanges data with an EtherCAT master. Currently I have to use the cifX32dll.dll to exchange data with the master, but this dll resides in the user space. Hence I am using the toolkit to write the necessary functions that will work in kernel mode.
As written above this will cause problems as there will be two instances (cifXdrv.sys AND your application) accessing the DPM AND the handshake flags.
Do you have some code that shows how to get a pointer to the DPM? In the toolkit you still rely on the cifx32dll.dll to get the DPM pointer?
If you want to handle the card yourself you will need to either write a dummy driver to make Windows happy and install that (instead of cifxdrv.sys) which does not do anything with the card, but offers an interface for your application, so you can use the whole toolkit inside your application, or you will need to provide a complete kernel mode driver containing the toolkit which offers a parallel interface to your application in kernel space.
cifXDrv.sys does not offer an internal IOCTL handler, thus it is not possible to do driver<-->driver communication in kernel space.
Another possibility to solve the user space issue: Is there a possibility to install a (kernel) callback function for channel events without going through the user space dll?
As the driver does not offer an inter-driver-IOCTL handler it is not possible to interface it in kernel mode.
Regards,
MT
chrbuss
Hi MT,
thank you for these instructions on how to port the toolkit.
I have a realtime application (part of a control system) running in kernel mode. This application works as an EtherCAT slave and exchanges data with an EtherCAT master. Currently I have to use the cifX32dll.dll to exchange data with the master, but this dll resides in the user space. Hence I am using the toolkit to write the necessary functions that will work in kernel mode.
Do you have some code that shows how to get a pointer to the DPM? In the toolkit you still rely on the cifx32dll.dll to get the DPM pointer?
Another possibility to solve the user space issue: Is there a possibility to install a (kernel) callback function for channel events without going through the user space dll?
Thank you very much in advance.
Regards, Christian