1、Funktionale SezifikationSchnittstelle fr den direkten Aufruf von Funktionen in externen Treibermodulen aus der SoftPLC-RuntimefrWindows NT1. Welche Module werden eingehngt ?IO-Treiber werden durch Eintrge in den Registry-Key HKEY_LOCAL_MACHINESoftware3S Smart Software SolutionsCodesys SPRTPLCIO Driv
2、ers eingehngt. Hier wird ein Wert DriverXX“ eingetragen. XX ist dabei eine laufende Nummer, die mit 0 beginnend fr alle Treiber aufsteigend numeriert sein mu. Alle Funktionen, die sonst direkt auf der Hardware der Karte arbeiten wrden, werden nun auf Funktionen des externen Treibers umgeleitet.Diese
3、s Dokument beschreibt diese Schnittstelle speziell fr WindowsNT und die Echtzeiterweiterung von Smart Software Solutions.1.1. Die Anmeldeprozedur der Funtionszeiger.Jeder Treiber unter NT mu in seiner Initialisierungsfunktion (entry point) einige Eintrge in die Liste seiner Dispatch-Funtionen machen
4、, z.Bsp.:pDriverObject-MajorFunctionIRP_MJ_DEVICE_CONTROL= ntDeviceControl;pDriverObject-MajorFunctionIRP_MJ_CREATE = ntCreateFile;Hier kommt noch ein Eintrag hinzu, der dem System die Adresse der Kommunikationfunktion zwischen Treibern mitteilt:pDriverObject-MajorFunctionIRP_MJ_INTERNAL_DEVICE_CONT
5、ROL= yyyyyy;yyyyyy ist dabei die Adresse einer Funktion, die wie folgt definiert ist:typedef struct _tagCallbackInfo/the security-members are made to check, whether the caller is a legal caller to the driver.unsigned long ulSecurityId1; / this member must be set to 0x436F4465 means CoDeunsigned long
6、 ulSecurityId2; / this member must be set to 0x53797320 means Sysunsigned long ulCommand;unsigned long ulSubCommand;unsigned long ulCmdParam;void* pAdditionalCmdData; /may point to a caller-supplied, command-specific structure.CallbackInfo;unsigned long yyyyyy(CallbackInfo* pcbi, void* pPar);Diese F
7、unktion wird von der EchtzeitPLC aufgerufen, mit den SecurityIds1/2 wie oben beschrieben, so da der aufgerufene Treiber sofort berprfen kann, ob der Aufruf wirklich mit der oben beschriebenen Struktur vorgenommen wird.Wenn unter ulCommand dann noch DRV_CMD_GET_FUNCTION_POINTER_LIST“(#define DRV_CMD_
8、GET_FUNCTION_POINTER_LIST 1)bergeben wurde, ist pAdditionalCmdData ein Zeiger auf eine Funktionspointerliste.Dabei werden folgende Indizes verwendet:DRV_FCT_INIT 1DRV_FCT _EXIT 2DRV_FCT _GET_ID 3DRV_FCT _GET_FLAGS 4DRV_FCT _GET_IORANGE 5DRV_FCT _CONFIGURE_IONET 6DRV_FCT _CONFIGURE_MODULE 7DRV_FCT _C
9、ONFIGURE_DEVICE 8DRV_FCT _START_WRITE_OUTPUTS 9DRV_FCT _WRITE_OUTPUTS 10DRV_FCT _DONE_WRITE_OUTPUTS 11DRV_FCT _START_READ_INPUTS 12DRV_FCT _READ_INPUTS 13DRV_FCT _DONE_READ_INPUTS 14DRV_FCT_PLC_STATUS_CHANGES 15DRV_FCT_START_CONFIGURE_IONET,DRV_FCT_DONE_CONFIGURE_IONET,DRV_FCT_ENTER_NMI_ROUTINE,DRV_
10、FCT_LEAVE_NMI_ROUTINE,DRV_FCT_START_INTERRUPT,DRV_FCT_STOP_INTERRUPT,DRV_FCT_RETAIN_SAVE,DRV_FCT_RETAIN_RESTORE,DRV_FCT_CYCLIC_CALL,DRV_GET_EXTREFTABLEDRV_FCT_BUSDIAG_GETBUSSTATE,DRV_FCT_BUSDIAG_GETSTATE,DRV_FCT_BUSDIAG_SETBUSSTATE,DRV_FCT_BUSDIAG_SETSTATE,DRV_FCT_AFTERDOWNLOAD,DRV_FCT_PLCRESETHOOK,
11、DRV_FCT_PRECOMPUTE_SERVICE,DRV_FCT_POSTCOMPUTE_SERVICE,DRV_FCT_SRV_BROWSERCMD,DRV_FCT_ADD_BROWSERHELP,DRV_FCT_CST_PROCESSHOOK,DRV_FCT_GETTARGETIDS/hier erweiterbar durch 3S.Die Liste ist mit NULL initialisiert, der Treiber trgt hier seine Funktionsadressen durch Zuweisung ein:(void*)pAdditionalCmdDa
12、ta)DRV_FCT_INIT = yyyyyy, mit yyyyyy Name der Funktion, die den Treiber initialisiert. Mit allen Funktionen, die der Treiber der PLC anmelden will, wird so verfahren.Diese Anmeldeprozedur ist im Toolkit RTIO Drv Toolkit“ bereits implementiert. Die Stellen im Code, die unbedingt modifiziert werden me
13、n, damit ein funktionierender IO-Treiber resultiert, sind mit TODO: - Kommentaren versehen. Wann die einzelnen Funktionen vom Laufzeitsystem aufgerufen werden, entnehmen Sie dem Kapitel Funktionsbeschreibungen“.1.2. IO-Treiber mit dem RTIODrv_Toolkit erstellen.Hinweis: Das Toolkit ist dazu gedacht,
14、mit dem C+ - Compiler Microsoft Visual C+ 6.0“ Treiber fr NT4.0 zu erstellen.Um einen IO-Treiber, der von der EchtzeitSPS angesprochen werden soll, mit dem Toolkit zu generieren, men mindesten folgende Schritte beachtet werden:- Der Name einiger Quelldateien und die dazugehrigen Namen im Projektfile
15、 ndern. (Dazu die Dateien umbennen, dann einen neuen Workspace anlegen und das umbenannte Projektfile einfgen und dann manuell die umbenannten Quellfiles einfgen. (Alternativ knnen die beigefgten Workspace- und Projektfiles auch als Textfile geffnet und mit Suchen/Ersetzen bearbeitet werden. Dann en
16、tfllt der folgende Schritt.)- In Projekt/Einstellungen des Menus die Dateinamen von Executable for Debug Session“ und Linker“/Output file name“ auf den eigenen Dateinamen des Treibers anpassen, ebenfalls in PostBuildStep.- Im File (im Toolkit) RTIODrv (das jetzt mglichst RTIOdrvXYZ heien sollte) men
17、 die Namen der sog. Symbolic Links“, die angelegt bzw. gelscht werden, dem Namen des Treibers angepat werden.- In allen Files die (genderten) Namen der Headerdateien anpassen.Jetzt sollte sich der Treiber bersetzen lassen, und eine Datei .sys im %SystemRoot%System32Drivers-Verzeichnis angelegt worde
18、n sein.Dieser Treiber mu nun noch installiert werden, um ihn dem System bekannt zu machen.Dazu mu im Toolkit-Verzeichnis, im Unterverzeichnis Registration“ die Datei RTIOdrv.reg editiert und (wegen der bersichtlichkeit) unter .reg abgespeichert werden. Im .reg-file mu lediglich der Name des anzulege
19、nden Schlssels vonHKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesRTIOdrvzuHKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesgendert werden.Danach auf das File doppelklicken, der Treiber wird registriert.Nach dem Neustart des Rechners taucht der Treiber in der Gerteliste des Gertemanagers auf und ka
20、nn zum Testen manuell gestartet / beendet werden.2. Funktionsbeschreibungen2.1. DRV_FCT_INITDie Funktion wird immer aufgerufen, wenn die PLC initialisiert wird und wenn sich die Hardwarekonfiguration gendert hat. Prototyp:typedef unsigned long (*PF_INIT)(unsigned long ulPar);mit ulPar:#define DRV_IN
21、IT_FLAG_HWCONFIG_CHANGED 0x1oder 0, wenn der Aufruf von der Initialisierungsphase der PLC kommt.Rckgabewerte 1 werden fr einen Fehlercode gehalten.2.2. DRV_FCT_EXITDie Funktion wird nur aufgerufen, wenn die PLC beendet wird.Prototyp:typedef unsigned long (*PF_EXIT)(void);Rckgabewert wird nicht ausge
22、wertet.2.3. DRV_FCT _GET_IDDie Funktion wird aufgerufen, wenn CoDeSys die Id (oder evtl. noch mehr Daten(Fr sptere Versionen) vom Treiber erfragen will.Prototyp:typedef unsigned long (*PF_GET_ID)(void* pDataMemory);Diese Funktion ist nicht optional, sie mu implementiert sein.Der Rckgabewert ist die
23、Id des Treibers, nach pDataMemory mu mit einer Zuweisung wie if(pDataMemory != NULL)*(unsigned long*)pDataMemory = Hier mu der Treiber mindestens 1 zuweisen, sonst wird er nie zur Konfiguration und nie zum IO-Update aufgerufen.Der Zugriff auf pDataMemory kann auch ber eine Struktur erfolgen, speziel
24、l wenn der Treiber auer der Anzahl der von ihm angesprochenen Gerte noch Informationen zu den von ihm benutzten Hardwareinterrupts an die PLC bermitteln will:Strukturdefinitionen:#pragma pack(1)/Structure for external use.typedef struct _tagINTERRUPT_DESCext/*If the driver connects via NT (IOConnect
25、Interrupt), it stores the IntVec received from NT here, to be called with the right parameters in case of a bluescreen. Attention: Any IO-driver that uses HW-interrupts must callKeRegisterBugCheckCallback, or in case of a bluescreen the system will hang if theres an interrupt for this driver.*/PKINT
26、ERRUPT pvIntVec;PVOID pContext;int iIntVec;/*If bConnectNow is true, the interrupt will be connected at once by the runtime to the specified driver-routine.But the driver itself must make sure, the interrupt is enabled. This is normally done by the OS.If bConnectNow is false, the interrupt will be c
27、onnected in case of a bluescreen, to make it possible for the IO-driver to work after a crash. NT must not be called in this case.*/char bConnectNow;INTERRUPT_DESCext;#pragma pack()#define MAX_DRV_INTERRUPT_ROUTINES 5/call 3S, if you have to handle more than 5 different interrupts!typedef BOOLEAN (*
28、PF_INTERRUPT_ROUTINE)(PKINTERRUPT pvIntVec, PVOID pContext);#pragma pack(1)typedef struct _GetIDdataint iNumDevices;int iNumInterruptRoutines;INTERRUPT_DESCext idIntDescMAX_DRV_INTERRUPT_ROUTINES;PF_INTERRUPT_ROUTINE apfIntRoutineMAX_DRV_INTERRUPT_ROUTINES;GetIDdata;#pragma pack()Der bergebene Point
29、er pDataMemory zeigt auf eine GetIDdata-struktur, die vom Treiber nur mit iNumDevices gefllt werden kann, aber auch komplett, falls der Treiber eine Interruptserviceroutine beim System angemeldet hat oder bei der PLC anmelden mchte.Ist bConnectNow = TRUE, wird der Interrupt von der PLC mit der Routi
30、ne verbunden, die angeben wird, ansonsten nur im Falle eines Bluescreens. Die Interruptserviceroutine mu in jedem Fall so wie angegeben definiert sein und wird mit den bergebenen Daten als PKINTERRUPT und pContext-Parameter aufgerufen.2.4. DRV_FCT _GET_FLAGSDie Funktion wird zu verschiedenen Gelegen
31、heiten aufgerufen, um die Fhigkeiten des Treibers abzufragen.Hier sollten folgende Flags (oder eine Kombination daraus) zurckgeliefert werden:DRV_CAP_FLAG_WANTS_CONFIG 0x1DRV_CAP_FLAG_IS_PBDEVICE 0x2DRV_CAP_FLAG_IS_CANDEVICE 0x4DRV_CAP_FLAG_IS_ASIDEVICE 0x8DRV_CAP_FLAG_IS_TCPIPDEVICE 0x10DRV_CAP_FLA
32、G_IS_ARCNETDEVICE 0x20DRV_CAP_FLAG_IS_IBSDEVICE 0x40DRV_CAP_FLAG_HAS_RETAINDATA_AREA 0x100/erweiterbar durch 3SDie Flags IS.DEVICE sind nur im Zusammenhang mit dem Flag .WANTS_CONFIG interessant. Wenn die HW-Konfigurationsdaten von CoDeSys benutzt werden sollen, um das IO-Gert zu konfigurieren, mu d
33、ie PLC wissen, welche Konfiguration benutzt werden soll. (z.B. CAN oder Profibus).Die Funktion liefert statisch immer den gleichen Wert zurck, wenn der Treiber nur ein Gert untersttzt, sonst natrlich die Flags fr das betreffende Gert.Das erste Gert (Device eines Treibers), das DRV_CAP_FLAG_HAS_RETAI
34、NDATA_AREA liefert, wird von der PLC als einziges aufgerufen, um Retain-Daten zu sichern / zu restaurieren (vorausgesetzt, da die jeweiligen Funktionszeiger nicht NULL sind).Prototy:typedef unsigned long (*PF_GET_FLAGS)(unsigned long ulDeviceNr2.5. DRV_FCT _GET_IORANGEDiese Funktion wird abgefragt,
35、nachdem der Treiber eingehngt wurde, um zu Wissen, fr welche IOs er aufgerufen werden soll.Prototyp:typedef void (*PF_GET_IORANGE)(unsigned long* pulOffset, unsigned long* pulSize);Der Treiber trgt in pulOffset/Size seine Daten ein. Fr IO-Offsets, die in diesen Bereich fallen, wird er dann beim IO-U
36、pdate einer Task aufgerufen. Wenn der Treiber mehrere Gerte untersttzt, so schreibt der Treiber an die bergebenen Adressen jeweils eine Liste mit Offsets/Sizes.2.6. DRV_FCT_START_CONFIGURE_IONETDie Funtion wird aufgerufen, bevor die ersten Konfigurationsdaten eines IO-Gerts gesendet (durch Aufrufe v
37、on CONFIGURE_MODULE bzw. CONFIGURE_DEVICE, also zu Beginn der Konfiguration. Damit kann z.B. eine auf der Karte laufende Konfiguration gestoppt und gelscht werden usw.Prototyp:typedef char (*PF_START_CONFIGURE_IONET)(unsigned long ulDeviceNr);Der Rckgabewert ist 0 oder 1 (0 fr Fehler) oder 1 fr Fehl
38、ercode.2.7. DRV_FCT_DONE_CONFIGURE_IONETDie Funtion wird aufgerufen, wenn das Netzwerk, das an das IO-Gert angeschlossen ist, konfiguriert werden soll, also zum Abschlu der Konfiguration.Prototyp:typedef char (*PF_DONE_CONFIGURE_IONET)(unsigned long ulDeviceNr);Der Rckgabewert ist 0 oder 1 (0 fr Feh
39、ler) oder 1 fr Fehlercode.2.8. DRV_FCT_CONFIGURE_MODULEDie Funktion wird fr jedes, an das IO-Netz angeschlossene Modul aufgerufen. Sie dient zur Vorbereitung der Konfiguration. Der Treiber kann die Daten sammeln und mit DRV_FCT _CONFIGURE_IONET an sein Gert senden, oder sofort an sein Gert weiterrei
40、chen usw.Prototyp:typedef char (*PF_CONFIGURE_MODULE)(int iModule, void* pModConfData, unsigned long ulDeviceNr);Je nachdem, um welches IO-Netz es sich handelt, wird mit verschiedenen Strukturen auf pModConfData zugegriffen. Diese Strukturen sind im Anhang definiert, sowie in den jeweiligen Header-D
41、ateien.2.9. DRV_FCT _CONFIGURE_DEVICEDie Funktion wird ebenfalls zur Vorbereitung der Konfiguration aufgerufen, um die Gerteparameter des IO-Gerts selbst, das zum Treiber gehrt, zu setzen.Der Treiber kann die Daten puffern und mit DRV_FCT _CONFIGURE_IONET an sein Gert senden, oder sie direkt zum Ger
42、t senden usw.Prototyp:typedef char (*PF_CONFIGURE_DEVICE)(void* pBusDesc, unsigned long ulDeviceNr);Je nachdem, um welches IO-Netz es sich handelt, wird mit verschiedenen Strukturen auf pBusDesc zugegriffen.2.10. DRV_FCT _START_WRITE_OUTPUTSDie Funktion wird aufgerufen, bevor die Ausgnge einer Task
43、geschrieben werden und kann zur Vorbereitung benutzt werden.Prototyp:typedef char (*PF_START_WRITE_OUTPUTS)(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice);Wenn die Funktion hier 0 zurckliefert, kann sie die folgenden Aufrufe zum Update der Ausgnge verhindern.2.11. DRV_FCT_WRITE_OUTP
44、UTSDie Funktion wird fr jeden Ausgangsblock, der einer Task zugeordnet wurde, einmal aufgerufen.Prototyp:typedef char (*PF_WRITE_OUTPUTS)(unsigned long ulOffset, unsigned long ulSize, unsigned char* pucDataSrc, unsigned long ulTaskNr, unsigned long ulDeviceNr);Liefert die Funktion hier 0 zurck, wird
45、 eine Exception generiert, die PLC mit Fehler ERROR_IO_UPDATE gestoppt.2.12. DRV_FCT _DONE_WRITE_OUTPUTSDie Funktion wird aufgerufen, nachdem die Ausgnge einer Task geschrieben wurden (durch Aufrufe von DRV_FCT_WRITE_OUTPUTS) und kann z.B. von DMA-Treibern benutzt werden, um nun die Datenpuffer zur
46、Karte zu bertragen.Prototyp:typedef char (*PF_DONE_WRITE_OUTPUTS)(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice);Wenn die Funktion hier 0 zurckliefert, wird eine Exception generiert, die PLC mit Fehler ERROR_IO_UPDATE gestoppt.2.13. START_READ_INPUT, READ_INPUT, DONE_READ_INPUTAnalo
47、g zu den Outputs.Prototypen:typedef char (*PF_START_READ_INPUTS)(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice);typedef char (*PF_READ_INPUTS)(unsigned long ulOffset, unsigned long ulSize, unsigned char* pucDataDest, unsigned long ulTaskNr, unsigned long ulDeviceNr);typedef char (*P
48、F_DONE_READ_INPUTS)(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice);2.14. DRV_FCT_PLC_STATUS_CHANGESDiese Funktion wird immer aufgerufen bevor der Status der PLC sich ndert, also z.B. von RUN in STOP geht.Prototyp:typedef char (*PF_PLC_STATUS_CHANGES)(unsigned char ucNewState);mit Ne
49、wState eins von/* Controller Status definitions */#define RTS_VOID (unsigned char)-1)#define RTS_RUN 0#define RTS_STOP_SRV 1#define RTS_STOP_BP 2#define RTS_RUN_STEP_IN 3#define RTS_RUN_STEP_OVER 4#define RTS_RUN_WATCHDOG 5Liefert die Funktion hier 0 zurck, kann sie den bergang zum Zustand RUN verhindern, nicht aber den bergang zu anderen Zustnden.2.15. DRV_FCT_ENTER_NMI_ROUTINEWenn die PLC