
Добавил:
kasak9595
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:8 СЕМЕСТР / АСУ ЭТО / Wago-IO-PRO CAA 2.3.8.5 (5.10.2007) / Setup_CoDeSys_SP_RTE / IODriver ToolKit / IOdrvFunctions
.c/*********************************************************************************/
/*This file contains all the functions, that make the IODrv. */
/*These functions are called from 3S-RTPLC as callbacks. */
/*********************************************************************************/
#include <ntddk.h>
#include "IOdrvInterface.h"
#include "IODrvFunctions.H"
#include "CardFunctions.h"
#include "RTIOdrv.h"
#define MAXIMUM_STRING_BUFFER 80
extern RtsApiInterface g_rtsapi;
/*globals */
char g_bValidIOdeviceFound = 0;
/***First do the initialization of the devices, and build complete information about them.**/
RTS_LAST_ERROR* s_pLastErr = NULL;
unsigned long IODrvInitIO(unsigned long ulPar)
{
//TODO: retrieve all available information about my devices: number, interrupt-descriptions, IOranges ...
s_pLastErr = IODrvGetLastError();
return 1;
}
unsigned long IODrvExitIO(void)
{
//TODO: free evtl. allocated memory in InitIO and all the things need to be done when the PLC exits.
//Note that IODrvInitIO/ExitIO may be called many times without terminating the driver.
//So do the things that need to be done once within the driver-runtime in DriverEntry.
//Important here: be aware that is fatal to call a function from g_rtsapi after this function has been called.
//So it is a good idea to delete the pointers in g_rtsapi.
memset((char*)&g_rtsapi,0,sizeof(g_rtsapi));
return 1;
}
unsigned long IODrvGetId(void* pData)
{
int iDev = 1; //this is the default to avoid IOinit-error, if this is 0.
GetIDdata* pgidd = (GetIDdata*)pData;
//TODO: determine the number of devices this driver manages.
// *(unsigned long*)pData = iDev; // The number of devices is important to the PLC!!
pgidd->iNumDevices = iDev;
/*
The informations about interrupts are optional.
pgidd->iNumInterruptRoutines = iDev; //Normally each device has his own interrupt.
for(i = 0; i < iMaster; i++)
{
pgidd->apfIntRoutine[i] = GlobalIsr;
pgidd->idIntDesc[i].bConnectNow = 0;
pgidd->idIntDesc[i].pContext = NULL;
pgidd->idIntDesc[i].pvIntVec = ptGlobalDrv->aDevInst[i].pvVirtualIrq;
pgidd->idIntDesc[i].iIntVec = ptGlobalDrv->aDevInst[i].usBoardIrq;
}
*/
return 0xffff; //The ID may be usefull to the runtime in future. Return your specific ID.
}
unsigned long IODrvGetDeviceFlags(unsigned long ulDeviceNr)
{
//TODO: return the device-capability flags, specific for each device.
//for example:
// return DRV_CAP_FLAG_WANTS_CONFIG | DRV_CAP_FLAG_IS_CANDEVICE;
return 0;
}
void IODrvGetIORange(unsigned long* pulOffset, unsigned long* pulSize)
{
int i = 0;
unsigned long ulOffs = 0;
//TODO: insert a list of offset and size of the io-range of each device, for example to handle all your devices as
//one block of IOs write (if your device-informations are stored in an array):
/*
while(a_dev[i].bDeviceAvailable && i < DRV_MAX_DEVICES )
{
pulSize[i] = a_Dev[i].ulSize;
pulOffset[i] = ulOffs;
ulOffs += a_dev[i].ulSize;
i++;
}
*/
}
char IODrvConfigureIONetStart(unsigned long ulDeviceNr)
{
//TODO: call the appropriate IODev-function IODevConfigureIONetStart, which may be different for each device, who knows.
return IODevConfigureIONetStart(ulDeviceNr);
//return 0;
}
char IODrvConfigureIONetDone(unsigned long ulDeviceNr)
{
//TODO: mark the device as configured (or do nothing, or send config-data now to the device or something like that.)
return 1;
}
char IODrvConfigureModule(int iModule, void* pModConfData, unsigned long ulDeviceNr)
{
//TODO: the structures are different for each supported kind of bus (see CAP_FLAGS)
//so determine with the device-nr, what config-function has to be called.
//Call the function that configures a PB-Slave.
/*
return IODevConfigOnePBSlave((char)iModule, //here iModule is stationnumber as contained in PBSlave
pModConfData, //points to a PBSlave-structure
(char)ulDeviceNr );//identifies the card
*/
//Call the function that configures a CAN-node.
/*
return IODevConfigOneCanNode((char)iModule, //here iModule is NodeAddress
pModConfData,//points to a CANnode-structure
(char)ulDeviceNr );//identifies the card
*/
return 0;
}
char IODrvConfigureDevice(void* pBusDesc, unsigned long ulDeviceNr)
{
//TODO: the structures are different for each supported kind of bus (see CAP_FLAGS)
//so determine with the device-nr, what config-function has to be called.
/* Example:
switch(bustype)
//Call the function that configures a PB-Master.
return IODevSetPBCardMasterParams(pBusDesc,(char)ulDeviceNr);
//Call the function that configures a CAN-Master.
return IODevSetCANCardMasterParams(pBusDesc,(char)ulDeviceNr);
*/
return 0;
}
char IODrvStartWriteOutputs(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice)
{
return 1;
}
char IODrvWriteOutput(unsigned long ulOffset, unsigned long ulSize, unsigned char* pucData, unsigned long ulTaskNr, int iDevice)
{
//TODO: call the specific function for that device.
return IODevWriteOutput(ulOffset, ulSize, pucData, ulTaskNr, iDevice);
}
char IODrvDoneWriteOutputs(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice)
{
//TODO: call the specific function for that device.
return IODevDoneWriteOutputs(ulTaskNr, ulCycleTime, iDevice);
}
char IODrvStartReadInputs(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice)
{
return 1;
}
char IODrvReadInput(unsigned long ulOffset, unsigned long ulSize, unsigned char* pucData, unsigned long ulTaskNr, int iDevice)
{
//TODO: call the specific function for that device.
return IODevReadInput(ulOffset, ulSize, pucData, ulTaskNr, iDevice);
}
char IODrvDoneReadInputs(unsigned long ulTaskNr, unsigned long ulCycleTime, int iDevice)
{
//TODO: call the specific function for that device.
return IODevDoneReadInputs(ulTaskNr, ulCycleTime, iDevice);
}
char IODrvPLCStatusChanges(char cNewState)
{
//TODO: if the IODrv wants to prevent the PLC from changing the current state
//(it is only possible for the driver to prevent the PLC changing from STOP to RUN, not the other way).
//by returning one or not registering this function, the driver is not involved into state-change.
return 1;
}
void IODrvEnterNMIRoutine(void)
{ //TODO: this routine is called when the NMI-handler is entered. It is very hardware-dependent to quit the NMI,
//so the hardware will produce the next NMI. Reactivate the NMI here for your HW.
}
void IODrvLeaveNMIRoutine(void)
{ //TODO: if there's something to do, before returning to 'normal' program-execution do it now!
}
int IODrvStartInterrupt(int iParam)
{
//TODO: if the driver wants to start a cyclic interrupt, the PLC-scheduler should use to schedule on.
//return the interrupt-vector of the cyclic interrupt. (Use IDT-indexes, not logical vectors!)
return -1;
}
int IODrvStopInterrupt(int iParam)
{
//TODO: stop generating a cyclic interrupt, the PLC will deinstall her handling-routine.
//The system will crash, if the interrupt is produced any longer.
//return the interrupt-vector of the cyclic interrupt. (Use IDT-indexes, not logical vectors!)
return -1;
}
unsigned long IODrvRetainSave(unsigned short sSegment, unsigned char *pbyData, unsigned long ulSize, int iDevice)
{ //TODO: this routine is called whenever a task wants to save retain-data and the driver did tell the PLC (by CAP-flag)
//he will save retain-data.
return (unsigned long)-1;
}
unsigned long IODrvRetainRestore(unsigned short sSegment, unsigned char *pbyData, unsigned long ulSize, int iDevice)
{ //TODO: this routine is called everytime the PLC loads a bootproject and the driver has set the flag CAN_SAVE_RETAIN
//read the retain-data from whereever you saved it and store it to pbyData, maximum ulSize bytes.
//return 1; //restoring the retains was successfull.
return (unsigned long)-1;
}
unsigned long IODrvCyclicCallback(__int64* pliCurTime)
{ //TODO: this routine is called by the scheduler itself, if the pointer to the function is specified
// in the functionpointerlist. The returnvalue specifies, in how many ms it is called next time.
// BE CAREFULL !! This functions is called save from interrupts. Its duration is directly added to the
// scheduler's duration. So don't stay longer than max.100us in this function.
return 500; //Get the next call in 500ms.
}
static void _cdecl Dummy(void)
{
}
static ExtRef IOdrvExtRefTable[] =
{ //TODO: if you have own lib-function, to be called from IEC-tasks, insert here.(Then 'Dummy' can be removed.)
//Remember: All functions added here may be called from IEC-tasks (CoDeSys-generated code, so they all MUST be declared as _cdecl !!!
//(Otherwise unpredictable system crashes may occur, because of stack-faults.)
{"Dummy", (void (*)())Dummy},
{"", NULL}
};
void* IODrvGetExtRefTable(void)
{
return IOdrvExtRefTable;
}
unsigned long IODrvProcessHook(unsigned long ulHook, unsigned long ulAdditionalInfo)
{
char bCustomHandling = FALSE;
switch (ulHook)
{
case PH_BEFORE_RESET:
case PH_AFTER_RESET:
{
unsigned char byResetMode = (unsigned char)ulAdditionalInfo;
return 1;
}
default:
break;
}
return 0;
}
unsigned long IODrvPreComputeService(unsigned char* pbyReceive, unsigned long ulRecvLen, unsigned char* pbySend)
{ //returns the number of bytes it writes to pbySend.
unsigned char byService;
byService = pbyReceive[0];
switch (byService)
{
default:
break;
}
return 0;
}
unsigned long IODrvPostComputeService(unsigned char* pbyReceive, unsigned long ulRecvLen, unsigned char* pbySend, unsigned long ulSendLen)
{ //returns the number of bytes it writes to pbySend.
unsigned char byService;
byService = pbyReceive[0];
switch (byService)
{
default:
break;
}
return 0;
}
unsigned int IODrvSrvBrowserCmds(char* pszCommand, char* pszAnswer, unsigned int iSubCommand, unsigned int iBlockNr, char* pcActiveBrowserCommand)
{
/* pszAnswer is the pointer to the buffer, where the answerstring is to be added. Terminate with zero!! */
/* iSubCommand is the active command to be executed. */
/* iBlockNr is incremented each time the function is called. The function is called as long as it adds PLC_SUB_FOLLOWINGS */
/* The function will not be called again for this command if it adds PLC_SUB_LAST. */
/* The first byte added to the answer MUST be PLC_SUB_LAST / FOLLOWINGS. */
/* This must look like
if (iBlockNr > (something to decide wether the command reached its end) )
{
*pcActiveBrowserCommand=BROWSERCMD_NOCMD; Clear the active browsercommand !!
*(pszAnswer++)=(unsigned char)PLC_SUB_LAST; Tell the communication-partner: All data is sent now!!
}
else
*(pszAnswer++)=(unsigned char)PLC_SUB_FOLLOWINGS; */
char* pszAnswerStart;
char szKeyWord[21];
unsigned int i, ii=0;
short bIsCharacter=0;
for(i=0;(i<strlen(pszCommand) && i<20);i++)
{
if (pszCommand[i]!=' ' && pszCommand[i]!='\t')
bIsCharacter=1;
if (bIsCharacter!=0 && (pszCommand[i]==' ' || pszCommand[i]=='\t'))
break; /*first space after a non-space, e.g.first word was read.*/
if (bIsCharacter!=0)
szKeyWord[ii++]=pszCommand[i];
}
szKeyWord[ii]='\0';
if(strcmp(szKeyWord,"testit")==0)
*pcActiveBrowserCommand = BROWSERCMD_USERTEST;
switch(*pcActiveBrowserCommand)
{
case BROWSERCMD_USERTEST:
if(iBlockNr<10)
*(pszAnswer++)=(unsigned char)PLC_SUB_FOLLOWINGS; /*Tell the communication-partner: Not all data is sent !!*/
else
{
*pcActiveBrowserCommand=BROWSERCMD_NOCMD; /*Clear the active browsercommand !! */
*(pszAnswer++)=(unsigned char)PLC_SUB_LAST; /*Tell the communication-partner: All data is sent now!! */
}
*(pszAnswer++)=(unsigned char)0x00;
/*increment block-nr and send new blocknr within answer*/
iBlockNr++;
*(pszAnswer++)=(char)(iBlockNr & 0xff);
*(pszAnswer++)=(char)((iBlockNr>>8) & 0xff);
pszAnswerStart = pszAnswer;
*(pszAnswer++) = (char)(iBlockNr + 64);
pszAnswer += strlen(strcpy(pszAnswer," That's the testanwer f. CstBrowserCmd."));
*(pszAnswer++)='\0';
break;
default:
return 0;
}
return strlen(pszAnswerStart);
}
unsigned int IODrvAddBrowserhelp(char* pszAnswer, unsigned short usCurNr)
{
unsigned short ii;
const char szHelp[]={"testit - get the testanswer from IODrvSrvBrowserCmds\r\nCustom help Nr.1\r\nCustom help Nr.2\r\nCustom help Nr.3"};
for(ii=0;szHelp[ii] != '\0'; ii++)
*(pszAnswer++)=szHelp[ii];
*(pszAnswer++) = '\0';
return strlen(szHelp);
}
ProjectInfo* IODrvGetProjectInfo(void)
{
if(g_rtsapi.pfRtsGetProjectInfo != NULL)
return (*g_rtsapi.pfRtsGetProjectInfo)();
return NULL;
}
/*The functions called by BusDiagLib-functioncalls*/
/*
The driver must determine with the name, whether the call is destinated to himself.
If DRIVERNAME is NULL, always accept the call, the requested state may be the master/node first-level-stateinfo,
called from IOupdate of the PLC-task(s).
*/
void IODrvLibGetBusState(BUSDIAGLIB_GETBUSSTATEtyp* pinst)
{
if(memcmp(pinst->DRIVERNAME,MY_IODRV_NAME,strlen(MY_IODRV_NAME)) != 0)
return ;
}
void IODrvLibSetBusState(BUSDIAGLIB_SETBUSSTATEtyp* pinst)
{
if(memcmp(pinst->DRIVERNAME,MY_IODRV_NAME,strlen(MY_IODRV_NAME)) != 0)
return ;
}
void IODrvLibGetState(BUSDIAGLIB_GETSTATEtyp* pinst)
{
if(memcmp(pinst->DRIVERNAME,MY_IODRV_NAME,strlen(MY_IODRV_NAME)) != 0)
return ;
}
void IODrvLibSetState(BUSDIAGLIB_SETSTATEtyp* pinst)
{
if(memcmp(pinst->DRIVERNAME,MY_IODRV_NAME,strlen(MY_IODRV_NAME)) != 0)
return ;
}
/*The functions for task-handling-interface. They can also be called directly, but it's easier to encapsulate these calls.*/
int IODrvCreateTask(int iPriority, unsigned long ulCycleTime, int (*pfEntry)(void*), void* pArg, unsigned long ulFlags)
{
if(g_rtsapi.pfRtsCreateTask != NULL)
return (*g_rtsapi.pfRtsCreateTask)(iPriority, ulCycleTime, pfEntry, pArg, ulFlags);
return -1;
}
int IODrvDeleteTask(int iPriority)
{
if(g_rtsapi.pfRtsDeleteTask != NULL)
return (*g_rtsapi.pfRtsDeleteTask)(iPriority);
return -1;
}
int IODrvWaitForObject(int iWaitObjectNr, unsigned long ulMaxTime)
{
if(g_rtsapi.pfRtsWaitForObject != NULL)
return (*g_rtsapi.pfRtsWaitForObject)(iWaitObjectNr,ulMaxTime);
return -1;
}
int IODrvSetObject(int iWaitObjectNr)
{
if(g_rtsapi.pfRtsSetObject != NULL)
return (*g_rtsapi.pfRtsSetObject)(iWaitObjectNr);
return -1;
}
int IODrvSleep(unsigned long ulSleepTime)
{
if(g_rtsapi.pfRtsSleep != NULL)
return (*g_rtsapi.pfRtsSleep)(ulSleepTime);
return -1;
}
int IODrvResume(int iPriority)
{
if(g_rtsapi.pfRtsResume != NULL)
return (*g_rtsapi.pfRtsResume)(iPriority);
return -1;
}
int IODrvSuspend(int iPriority)
{
if(g_rtsapi.pfRtsSuspend != NULL)
return (*g_rtsapi.pfRtsSuspend)(iPriority);
return -1;
}
/*The functions for asynchronuous fileaccess.*/
int IOdrvAsynchFileOpen(void** pHandle,unsigned long ulAttributes,char* pszName)
{
if(g_rtsapi.pfAsynchFileOpen != NULL)
return (*g_rtsapi.pfAsynchFileOpen)(pHandle,ulAttributes,pszName);
return -1;
}
int IOdrvAsynchFileClose(void* Handle)
{
if(g_rtsapi.pfAsynchFileClose != NULL)
return (*g_rtsapi.pfAsynchFileClose)(Handle);
return -1;
}
int IOdrvAsynchFileRead(void* Handle, char* pBuffer, unsigned long ulSize)
{
if(g_rtsapi.pfAsynchFileRead != NULL)
return (*g_rtsapi.pfAsynchFileRead)(Handle,pBuffer,ulSize);
return -1;
}
int IOdrvAsynchFileWrite(void* Handle, char* pBuffer, unsigned long ulSize)
{
if(g_rtsapi.pfAsynchFileWrite != NULL)
return (*g_rtsapi.pfAsynchFileWrite)(Handle,pBuffer,ulSize);
return -1;
}
int IOdrvSynchFileOpen(void** pHandle,unsigned long ulAttributes,char* pszName)
{
int iRet;
while((iRet = IOdrvAsynchFileOpen(pHandle,ulAttributes,pszName)) < Done)
{
IODrvSleep(100);
}
return iRet;
}
int IOdrvSynchFileClose(void* Handle)
{
int iRet;
while((iRet = IOdrvAsynchFileClose(Handle)) < Done)
{
IODrvSleep(100);
}
return iRet;
}
int IOdrvSynchFileRead(void* Handle, char* pBuffer, unsigned long ulSize)
{
int iRet;
while((iRet = IOdrvAsynchFileRead(Handle,pBuffer,ulSize)) < Done)
{
IODrvSleep(100);
}
return iRet;
}
int IOdrvSynchFileWrite(void* Handle, char* pBuffer, unsigned long ulSize)
{
int iRet;
while((iRet = IOdrvAsynchFileWrite(Handle,pBuffer,ulSize)) < Done)
{
IODrvSleep(100);
}
return iRet;
}
char IODrvGetTargetIds(unsigned long *pulIOTrgId, unsigned long *pulIOHookId)
{
char cResult = TRUE; //Set FALSE, if IODrv doesn't want to determine the ID.
if(cResult)
{
*pulIOTrgId = 4711;
*pulIOHookId = 0;
return 1; //Yes, take this ID!
}
else
return 0; //No, I don't want to overwrite the target ID.
}
RTS_LAST_ERROR* IODrvGetLastError(void)
{
if(g_rtsapi.pfRtsDataManipulation != NULL)
return (RTS_LAST_ERROR*)(*g_rtsapi.pfRtsDataManipulation)(DTAMAN_MODE_GETLASTERROR,0);
return 0;
}
int IODrvGetSystemTimeFromBoot(__int64* pil)
{
if(g_rtsapi.pfRtsDataManipulation != NULL)
{
(*g_rtsapi.pfRtsDataManipulation)(DTMAN_MODE_GETSYSTEMTIMEFROMBOOT,(unsigned long)pil);
return 1;
}
return 0;
}
char* IODrvGetAddress(unsigned long ulSegment)
{
if(g_rtsapi.pfRtsDataManipulation != NULL)
return (char*)(*g_rtsapi.pfRtsDataManipulation)(DTMAN_MODE_GETADDRESS,ulSegment);
return 0;
}
unsigned long IODrvGetSegSize(unsigned long ulSegment)
{
if(g_rtsapi.pfRtsDataManipulation != NULL)
return (*g_rtsapi.pfRtsDataManipulation)(DTMAN_MODE_GETSEGSIZE,ulSegment);
return 0;
}
long IODrvGetIdentity(void)
{
if(g_rtsapi.pfRtsDataManipulation != NULL)
return (long)(*g_rtsapi.pfRtsDataManipulation)(DTMAN_MODE_GETIDENTITY,0);
return 0;
}
Соседние файлы в папке IODriver ToolKit