author | Paula Carrillo <p-carrillo@ti.com> | |
Fri, 17 Feb 2017 23:39:40 +0000 (17:39 -0600) | ||
committer | Paula Carrillo <p-carrillo@ti.com> | |
Fri, 17 Feb 2017 23:39:40 +0000 (17:39 -0600) |
447 files changed:
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemo.cpp b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemo.cpp
--- /dev/null
@@ -0,0 +1,1163 @@
+/*-----------------------------------------------------------------------------
+ * ATEMDemo.cpp
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description EtherCAT Master demo application
+ *---------------------------------------------------------------------------*/
+
+/*-INCLUDES------------------------------------------------------------------*/
+#include <AtEthercat.h>
+
+#include <..\..\Workspace\SYSBIOS_AM57xx\emllICSS\icssEmacEcDevice.h>
+
+#ifdef TTS
+uint8_t tts_demo_over = EC_FALSE;
+uint8_t ttsInitCompleted = EC_FALSE;
+EC_T_BYTE init_ok = -1;
+uint32_t maxJitter =0;
+#endif
+
+#include "ATEMDemo.h"
+#include "Logging.h"
+
+#ifdef ATEMRAS_SERVER
+#include <AtEmRasSrv.h>
+#endif
+
+/*-DEFINES-------------------------------------------------------------------*/
+#define LogMsg S_poLog->LogMsg
+#define LogError S_poLog->LogError
+
+/*-LOCAL VARIABLES-----------------------------------------------------------*/
+static EC_T_DWORD S_dwClntId = 0;
+static CAtEmLogging* S_poLog = EC_NULL;
+static T_DEMO_THREAD_PARAM S_DemoThreadParam = {0};
+static EC_T_PVOID S_pvtJobThread = EC_NULL;
+#ifdef ATEMRAS_SERVER
+static EC_T_BOOL S_bRasSrvStarted = EC_FALSE;
+static EC_T_PVOID S_pvRemoteApiSrvH = EC_NULL;
+#endif
+static EC_T_BOOL S_bEnaPerfJobs = EC_FALSE;
+static EC_T_TSC_MEAS_DESC S_TscMeasDesc;
+static EC_T_CHAR* S_aszMeasInfo[MAX_JOB_NUM] =
+{
+ (EC_T_CHAR*)"JOB_ProcessAllRxFrames",
+ (EC_T_CHAR*)"JOB_SendAllCycFrames ",
+ (EC_T_CHAR*)"JOB_MasterTimer ",
+ (EC_T_CHAR*)"JOB_SendAcycFrames ",
+ (EC_T_CHAR*)"Cycle Time ",
+ (EC_T_CHAR*)"myAppWorkPd "
+};
+
+/*-FORWARD DECLARATIONS------------------------------------------------------*/
+static EC_T_DWORD ecatNotifyCallback(EC_T_DWORD dwCode, EC_T_NOTIFYPARMS* pParms);
+#if (defined ATEMRAS_SERVER)
+static EC_T_DWORD RasNotifyWrapper(EC_T_DWORD dwCode, EC_T_NOTIFYPARMS* pParms);
+#endif
+static EC_T_VOID tEcJobTask(EC_T_VOID* pvThreadParamDesc);
+
+/*-MYAPP---------------------------------------------------------------------*/
+/* Demo code: Remove/change this in your application */
+static EC_T_DWORD myAppInit (CAtEmLogging* poLog, EC_T_INT nVerbose);
+static EC_T_DWORD myAppPrepare (CAtEmLogging* poLog, EC_T_INT nVerbose);
+static EC_T_DWORD myAppSetup (CAtEmLogging* poLog, EC_T_INT nVerbose, EC_T_DWORD dwClntId);
+static EC_T_DWORD myAppWorkpd (CAtEmLogging* poLog, EC_T_INT nVerbose, EC_T_BYTE* pbyPDIn, EC_T_BYTE* pbyPDOut);
+static EC_T_DWORD myAppDiagnosis(CAtEmLogging* poLog, EC_T_INT nVerbose);
+static EC_T_DWORD myAppNotify (EC_T_DWORD dwCode, EC_T_NOTIFYPARMS* pParms);
+/* Demo code: End */
+
+/*-FUNCTION DEFINITIONS------------------------------------------------------*/
+
+/********************************************************************************/
+/** \brief EtherCAT Master demo Application.
+*
+* This is a EtherCAT Master demo application.
+*
+* \return Status value.
+*/
+EC_T_DWORD ATEMDemo(
+ CAtEmLogging* poLog
+ ,EC_T_CNF_TYPE eCnfType /* [in] Enum type of configuration data provided */
+ ,EC_T_PBYTE pbyCnfData /* [in] Configuration data */
+ ,EC_T_DWORD dwCnfDataLen /* [in] Length of configuration data in byte */
+ ,EC_T_DWORD dwBusCycleTimeUsec /* [in] bus cycle time in usec */
+ ,EC_T_INT nVerbose /* [in] verbosity level */
+ ,EC_T_DWORD dwDuration /* [in] test duration in msec (0 = forever) */
+ ,EC_T_LINK_PARMS* poLinkParms /* [in] pointer to link parameter */
+ ,EC_T_VOID* pvTimingEvent /* [in] Timing event handle */
+ ,EC_T_DWORD dwCpuIndex /* [in] SMP only: CPU index */
+ ,EC_T_BOOL bEnaPerfJobs /* [in] Performance measurement */
+#ifdef ATEMRAS_SERVER
+ ,EC_T_WORD wServerPort /* [in] Remote API Server Port */
+#endif
+ ,EC_T_LINK_PARMS* poLinkParmsRed /* [in] Redundancy Link Layer Parameter */
+)
+{
+ EC_T_DWORD dwRetVal = EC_E_NOERROR;
+ EC_T_DWORD dwRes = EC_E_NOERROR;
+ EC_T_BOOL bRes = EC_FALSE;
+ CEcTimer oTimeout;
+ CEmNotification* pNotification = EC_NULL;
+
+ /* store parameters */
+ S_poLog = poLog;
+ S_bEnaPerfJobs = bEnaPerfJobs;
+ S_DemoThreadParam.pvTimingEvent = pvTimingEvent;
+
+ /* check if interrupt mode is selected */
+ if (poLinkParms->eLinkMode != EcLinkMode_POLLING)
+ {
+ dwRetVal = EC_E_INVALIDPARM;
+ LogError("Error: Link layer in 'interrupt' mode is not supported by EcMasterDemo. Please select 'polling' mode.");
+ goto Exit;
+ }
+ /* set thread affinity */
+ {
+ EC_T_CPUSET CpuSet;
+
+ EC_CPUSET_ZERO(CpuSet);
+ EC_CPUSET_SET(CpuSet, dwCpuIndex);
+ bRes = OsSetThreadAffinity(EC_NULL, CpuSet);
+ if (!bRes)
+ {
+ dwRetVal = EC_E_INVALIDPARM;
+ LogError("Error: Set thread affinitiy, invalid CPU index %d\n", dwCpuIndex);
+ goto Exit;
+ }
+ }
+ /* create notification context */
+ pNotification = EC_NEW(CEmNotification(INSTANCE_MASTER_DEFAULT, poLog));
+ if (EC_NULL == pNotification)
+ {
+ dwRetVal = EC_E_NOMEMORY;
+ goto Exit;
+ }
+ pNotification->Verbose(nVerbose);
+
+ if (S_bEnaPerfJobs)
+ {
+ PERF_MEASURE_JOBS_INIT(EC_NULL);
+ }
+
+ /* Demo code: Remove/change this in your application: Initialize application */
+ /*****************************************************************************/
+ dwRes = myAppInit(poLog, nVerbose);
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError( (EC_T_CHAR*)"myAppInit failed, error code: 0x%x", dwRes );
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+#ifdef ATEMRAS_SERVER
+ /*******************************/
+ /* Start RAS server if enabled */
+ /*******************************/
+ if (0xFFFF != wServerPort)
+ {
+ ATEMRAS_T_SRVPARMS oRemoteApiConfig;
+
+ OsMemset(&oRemoteApiConfig, 0, sizeof(ATEMRAS_T_SRVPARMS));
+ oRemoteApiConfig.oAddr.dwAddr = 0; /* INADDR_ANY */
+ oRemoteApiConfig.wPort = wServerPort;
+ oRemoteApiConfig.dwCycleTime = REMOTE_CYCLE_TIME; /* 2 msec */
+ oRemoteApiConfig.dwWDTOLimit = (REMOTE_WD_TO_LIMIT/REMOTE_CYCLE_TIME); /* WD Timeout after 10secs */
+ oRemoteApiConfig.dwReConTOLimit = 6000; /* Reconnect Timeout after 6000*2msec + 10secs */
+ oRemoteApiConfig.dwMasterPrio = MAIN_THREAD_PRIO;
+ oRemoteApiConfig.dwClientPrio = MAIN_THREAD_PRIO;
+ oRemoteApiConfig.pvNotifCtxt = pNotification; /* Notification context */
+ oRemoteApiConfig.pfNotification = RasNotifyWrapper; /* Notification function for emras Layer */
+ oRemoteApiConfig.dwConcNotifyAmount = 100; /* for the first pre-allocate 100 Notification spaces */
+ oRemoteApiConfig.dwMbxNotifyAmount = 50; /* for the first pre-allocate 50 Notification spaces */
+ oRemoteApiConfig.dwMbxUsrNotifySize = 3000; /* 3K user space for Mailbox Notifications */
+ oRemoteApiConfig.dwCycErrInterval = 500; /* span between to consecutive cyclic notifications of same type */
+ if (0 != nVerbose) LogMsg("Start Remote API Server now\n");
+ dwRes = emRasSrvStart(oRemoteApiConfig, &S_pvRemoteApiSrvH);
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError("ERROR: Cannot spawn Remote API Server\n");
+ }
+ S_bRasSrvStarted = EC_TRUE;
+ }
+#endif
+ /******************************/
+ /* Initialize EtherCAT master */
+ /******************************/
+ if (0 != nVerbose) LogMsg( "==========================" );
+ if (0 != nVerbose) LogMsg( "Initialize EtherCAT Master" );
+ if (0 != nVerbose) LogMsg( "==========================" );
+ {
+ EC_T_INIT_MASTER_PARMS oInitParms;
+
+ OsMemset(&oInitParms, 0, sizeof(EC_T_INIT_MASTER_PARMS));
+ oInitParms.dwSignature = ATECAT_SIGNATURE;
+ oInitParms.dwSize = sizeof(EC_T_INIT_MASTER_PARMS);
+ oInitParms.pLinkParms = poLinkParms;
+ oInitParms.pLinkParmsRed = poLinkParmsRed;
+ oInitParms.dwBusCycleTimeUsec = dwBusCycleTimeUsec;
+ oInitParms.dwMaxBusSlaves = MASTER_CFG_ECAT_MAX_BUS_SLAVES;
+ oInitParms.dwMaxQueuedEthFrames = MASTER_CFG_MAX_QUEUED_ETH_FRAMES;
+ oInitParms.dwMaxSlaveCmdPerFrame = MASTER_CFG_MAX_SLAVECMD_PER_FRAME;
+ if (dwBusCycleTimeUsec < 1000)
+ {
+ oInitParms.dwMaxSentQueuedFramesPerCycle = 1;
+ }
+ else
+ {
+ oInitParms.dwMaxSentQueuedFramesPerCycle = MASTER_CFG_MAX_SENT_QUFRM_PER_CYC;
+ }
+ oInitParms.dwEcatCmdMaxRetries = MASTER_CFG_ECAT_CMD_MAX_RETRIES;
+ oInitParms.dwEoETimeout = MASTER_CFG_EOE_TIMEOUT;
+ oInitParms.dwFoEBusyTimeout = MASTER_CFG_FOE_BUSY_TIMEOUT;
+ oInitParms.dwLogLevel = nVerbose;
+ oInitParms.pfLogMsgCallBack = CAtEmLogging::OsDbgMsgHookWrapper;
+ dwRes = ecatInitMaster(&oInitParms);
+ if (dwRes != EC_E_NOERROR)
+ {
+ dwRetVal = dwRes;
+ LogError("Cannot initialize EtherCAT-Master! (Result = %s 0x%x)", ecatGetText(dwRes), dwRes);
+ goto Exit;
+ }
+ }
+
+ /* Create cyclic task to trigger master jobs */
+ /*********************************************/
+ S_DemoThreadParam.bJobThreadRunning = EC_FALSE;
+ S_DemoThreadParam.bJobThreadShutdown = EC_FALSE;
+ S_DemoThreadParam.pLogInst = S_poLog;
+ S_DemoThreadParam.pNotInst = pNotification;
+ S_DemoThreadParam.dwCpuIndex = dwCpuIndex;
+ S_DemoThreadParam.dwBusCycleTimeUsec = dwBusCycleTimeUsec;
+ S_pvtJobThread = OsCreateThread((EC_T_CHAR*)"tEcJobTask", tEcJobTask,
+#if !(defined EC_VERSION_GO32)
+ JOBS_THREAD_PRIO,
+#else
+ dwBusCycleTimeUsec,
+#endif
+ JOBS_THREAD_STACKSIZE, (EC_T_VOID*)&S_DemoThreadParam);
+#ifdef RTAI
+ OsMakeThreadPeriodic(S_pvtJobThread, dwBusCycleTimeUsec);
+#endif
+ /* wait until thread is running */
+ oTimeout.Start(2000);
+ while (!oTimeout.IsElapsed() && !S_DemoThreadParam.bJobThreadRunning)
+ {
+ OsSleep(10);
+ }
+ if (!S_DemoThreadParam.bJobThreadRunning)
+ {
+ dwRetVal = EC_E_TIMEOUT;
+ LogError("Timeout starting JobTask");
+ goto Exit;
+ }
+ oTimeout.Stop();
+
+ /* Configure master */
+ dwRes = ecatConfigureMaster(eCnfType, pbyCnfData, dwCnfDataLen);
+ if (dwRes != EC_E_NOERROR)
+ {
+ dwRetVal = dwRes;
+ LogError("Cannot configure EtherCAT-Master! %s (Result = 0x%x)", ecatGetText(dwRes), dwRes);
+ goto Exit;
+ }
+
+ /* Register client */
+ {
+ EC_T_REGISTERRESULTS oRegisterResults;
+
+ OsMemset(&oRegisterResults, 0, sizeof(EC_T_REGISTERRESULTS));
+ dwRes = ecatRegisterClient(ecatNotifyCallback, pNotification, &oRegisterResults);
+ if (dwRes != EC_E_NOERROR)
+ {
+ dwRetVal = dwRes;
+ LogError("Cannot register client! (Result = 0x%x)", dwRes);
+ goto Exit;
+ }
+ S_dwClntId = oRegisterResults.dwClntId;
+ pNotification->SetClientID(S_dwClntId);
+ }
+
+ /* Print found slaves */
+ if (nVerbose >= 2)
+ {
+ dwRes = ecatScanBus(ETHERCAT_SCANBUS_TIMEOUT);
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("Cannot scan bus: %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ PrintSlaveInfos(INSTANCE_MASTER_DEFAULT, poLog);
+ }
+
+ /* Print MAC address */
+ if (nVerbose > 0)
+ {
+ ETHERNET_ADDRESS oSrcMacAddress;
+
+ dwRes = ecatGetSrcMacAddress(&oSrcMacAddress);
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("Cannot get MAC address! (Result = 0x%x)", dwRes);
+ }
+ LogMsg("EtherCAT network adapter MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",
+ oSrcMacAddress.b[0], oSrcMacAddress.b[1], oSrcMacAddress.b[2], oSrcMacAddress.b[3], oSrcMacAddress.b[4], oSrcMacAddress.b[5]);
+ }
+
+ /* Start EtherCAT bus --> set Master state to OPERATIONAL if ENI file provided */
+ /*******************************************************************************/
+ if (0 != nVerbose) LogMsg( "=====================" );
+ if (0 != nVerbose) LogMsg( "Start EtherCAT Master" );
+ if (0 != nVerbose) LogMsg( "=====================" );
+
+ /* set master and bus state to INIT */
+ dwRes = ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_INIT);
+ pNotification->ProcessNotificationJobs();
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("Cannot start set master state to INIT (Result = %s (0x%lx))", ecatGetText(dwRes), dwRes);
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+
+ /******************************************************/
+ /* Demo code: Remove/change this in your application */
+ /******************************************************/
+ dwRes = myAppPrepare(poLog, nVerbose);
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError((EC_T_CHAR*)"myAppPrepare failed, error code: 0x%x", dwRes);
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+ /* set master and bus state to PREOP */
+ dwRes = ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_PREOP);
+ pNotification->ProcessNotificationJobs();
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("Cannot start set master state to PREOP (Result = %s (0x%lx))", ecatGetText(dwRes), dwRes);
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+ /* skip this step if demo started without ENI */
+ if (pbyCnfData != EC_NULL)
+ {
+ /******************************************************/
+ /* Demo code: Remove/change this in your application */
+ /******************************************************/
+ dwRes = myAppSetup(poLog, nVerbose, S_dwClntId);
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError((EC_T_CHAR*)"myAppSetup failed, error code: 0x%x", dwRes);
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+ /* set master and bus state to SAFEOP */
+ dwRes = ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_SAFEOP);
+ pNotification->ProcessNotificationJobs();
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("Cannot start set master state to SAFEOP (Result = %s (0x%lx))", ecatGetText(dwRes), dwRes);
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+ /* set master and bus state to OP */
+ dwRes = ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_OP);
+ pNotification->ProcessNotificationJobs();
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("Cannot start set master state to OP (Result = %s (0x%lx))", ecatGetText(dwRes), dwRes);
+ dwRetVal = dwRes;
+ goto Exit;
+ }
+ }
+ else
+ {
+ if (0 != nVerbose) LogMsg("No ENI file provided. EC-Master started with generated ENI file.");
+ }
+
+ if (S_bEnaPerfJobs)
+ {
+ LogMsg("");
+ LogMsg("Job times during startup <INIT> to <%s>:", ecatStateToStr(ecatGetMasterState()));
+ PERF_MEASURE_JOBS_SHOW(); /* show job times */
+ LogMsg("");
+ ecatPerfMeasReset(&S_TscMeasDesc, 0xFFFFFFFF); /* clear job times of startup phase */
+ }
+
+#if (defined DEBUG) && (defined XENOMAI)
+ /* Enabling mode switch warnings for shadowed task */
+ dwRes = rt_task_set_mode(0, T_WARNSW, NULL);
+ if (0 != dwRes)
+ {
+ OsDbgMsg("EnableRealtimeEnvironment: rt_task_set_mode returned an error\n");
+ OsDbgAssert(EC_FALSE);
+ }
+#endif
+
+ /* run the demo */
+ if (dwDuration != 0)
+ {
+ oTimeout.Start(dwDuration);
+ }
+ while (bRun && (!oTimeout.IsStarted() || !oTimeout.IsElapsed()))
+ {
+ if (nVerbose >= 2)
+ {
+ PERF_MEASURE_JOBS_SHOW(); /* show job times */
+ }
+ bRun = !OsTerminateAppRequest();/* check if demo shall terminate */
+
+ /*****************************************************************************************/
+ /* Demo code: Remove/change this in your application: Do some diagnosis outside job task */
+ /*****************************************************************************************/
+ myAppDiagnosis(poLog, nVerbose);
+
+ /* process notification jobs */
+ pNotification->ProcessNotificationJobs();
+
+ OsSleep(5);
+ }
+
+ if (S_bEnaPerfJobs)
+ {
+ LogMsg("");
+ LogMsg("Job times before shutdown");
+ PERF_MEASURE_JOBS_SHOW(); /* show job times */
+ }
+
+Exit:
+
+ if (0 != nVerbose) LogMsg( "========================" );
+ if (0 != nVerbose) LogMsg( "Shutdown EtherCAT Master" );
+ if (0 != nVerbose) LogMsg( "========================" );
+
+ /* Stop EtherCAT bus --> Set Master state to INIT */
+ dwRes = ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_INIT);
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError("Cannot stop EtherCAT-Master! %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ /* Unregister client */
+ if (S_dwClntId != 0)
+ {
+ dwRes = ecatUnregisterClient(S_dwClntId);
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError("Cannot unregister client! %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ S_dwClntId = 0;
+ }
+
+#if (defined DEBUG) && (defined XENOMAI)
+ /* Disable PRIMARY to SECONDARY MODE switch warning */
+ dwRes = rt_task_set_mode(T_WARNSW, 0, NULL);
+ if (dwRes != 0)
+ {
+ OsDbgMsg("OsCreateThread: rt_task_set_mode returned error %d\n", dwRes);
+ OsDbgAssert(EC_FALSE);
+ }
+#endif /* XENOMAI */
+
+ /* Shutdown tEcJobTask */
+ S_DemoThreadParam.bJobThreadShutdown = EC_TRUE;
+ oTimeout.Start(2000);
+ while (S_DemoThreadParam.bJobThreadRunning && !oTimeout.IsElapsed())
+ {
+ OsSleep(10);
+ }
+ if (S_pvtJobThread != EC_NULL)
+ {
+ OsDeleteThreadHandle(S_pvtJobThread);
+ S_pvtJobThread = EC_NULL;
+ }
+#ifdef TTS
+ maxJitter= deInitTTS(emachandle2);
+#endif
+ /* Deinitialize master */
+ dwRes = ecatDeinitMaster();
+ if (EC_E_NOERROR != dwRes)
+ {
+ LogError("Cannot de-initialize EtherCAT-Master! %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+#ifdef ATEMRAS_SERVER
+ /* Stop RAS server */
+ if (S_bRasSrvStarted)
+ {
+ LogMsg("Stop Remote Api Server\n");
+
+ if (EC_E_NOERROR != emRasSrvStop(S_pvRemoteApiSrvH, 2000))
+ {
+ LogError("Remote API Server shutdown failed\n");
+ }
+ }
+#endif
+ if (S_bEnaPerfJobs)
+ {
+ PERF_MEASURE_JOBS_DEINIT();
+ }
+ /* delete notification context */
+ SafeDelete(pNotification);
+
+ return dwRetVal;
+}
+
+
+/********************************************************************************/
+/** \brief Trigger jobs to drive master, and update process data.
+*
+* \return N/A
+*/
+static EC_T_VOID tEcJobTask(EC_T_VOID* pvThreadParamDesc)
+{
+ EC_T_DWORD dwRes = EC_E_ERROR;
+ T_DEMO_THREAD_PARAM* pDemoThreadParam = (T_DEMO_THREAD_PARAM*)pvThreadParamDesc;
+ EC_T_CPUSET CpuSet;
+ EC_T_BOOL bPrevCycProcessed = EC_FALSE;
+ EC_T_INT nOverloadCounter = 0; /* counter to check if cycle time is to short */
+ EC_T_BOOL bOk;
+
+ EC_CPUSET_ZERO(CpuSet);
+ EC_CPUSET_SET(CpuSet, pDemoThreadParam->dwCpuIndex);
+ bOk = OsSetThreadAffinity(EC_NULL, CpuSet);
+ if (!bOk)
+ {
+ LogError("Error: Set job task affinitiy, invalid CPU index %d\n", pDemoThreadParam->dwCpuIndex);
+ goto Exit;
+ }
+
+ /* Start periodic task right before where it is used,
+ * otherwise, OsSleepTillTick() might fail if this thread is suspended before being able to call OsMakeThreadPeriodic() */
+#if (defined XENOMAI)
+ OsMakeThreadPeriodic(rt_task_self(), pDemoThreadParam->dwBusCycleTimeUsec);
+#endif
+
+ /* demo loop */
+ pDemoThreadParam->bJobThreadRunning = EC_TRUE;
+ do
+ {
+ /* wait for next cycle (event from scheduler task) */
+#ifdef TTS
+ if(!ttsInitCompleted)
+ {
+ init_ok=initTTS(emachandle2, (uint32_t)(pDemoThreadParam->dwBusCycleTimeUsec));
+ if(init_ok == 0)
+ {
+ ttsInitCompleted = EC_TRUE;
+ }
+ }
+ ICSS_EMAC_osalPendLock(ttsP1TxSem, SemaphoreP_WAIT_FOREVER);
+
+#else
+#if (defined RTAI) || (defined XENOMAI)
+ OsSleepTillTick(); /* period is set after creating jobtask */
+#else
+ OsWaitForEvent(pDemoThreadParam->pvTimingEvent, EC_WAITINFINITE);
+#endif /* !RTAI && !XENOMAI*/
+#endif //TTS
+
+ PERF_JOB_END(PERF_CycleTime);
+ PERF_JOB_START(PERF_CycleTime);
+
+ /* process all received frames (read new input values) */
+ PERF_JOB_START(JOB_ProcessAllRxFrames);
+ dwRes = ecatExecJob( eUsrJob_ProcessAllRxFrames, &bPrevCycProcessed );
+ if (EC_E_NOERROR != dwRes && EC_E_INVALIDSTATE != dwRes && EC_E_LINK_DISCONNECTED != dwRes)
+ {
+ LogError("ERROR: ecatExecJob( eUsrJob_ProcessAllRxFrames): %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ PERF_JOB_END(JOB_ProcessAllRxFrames);
+
+ if (EC_E_NOERROR == dwRes)
+ {
+ if (!bPrevCycProcessed)
+ {
+ /* it is not reasonable, that more than 5 continuous frames are lost */
+ nOverloadCounter += 10;
+ if (nOverloadCounter >= 50)
+ {
+ LogError( "Error: System overload: Cycle time too short or huge jitter!" );
+ }
+ else
+ {
+ LogError( "eUsrJob_ProcessAllRxFrames - not all previously sent frames are received/processed (frame loss)!" );
+ }
+ }
+ else
+ {
+ /* everything o.k.? If yes, decrement overload counter */
+ if (nOverloadCounter > 0) nOverloadCounter--;
+ }
+ }
+
+ /*****************************************************/
+ /* Demo code: Remove/change this in your application: Working process data cyclic call */
+ /*****************************************************/
+ PERF_JOB_START(PERF_myAppWorkpd);
+ myAppWorkpd(pDemoThreadParam->pLogInst, pDemoThreadParam->pNotInst->Verbose(), ecatGetProcessImageInputPtr(), ecatGetProcessImageOutputPtr());
+ PERF_JOB_END(PERF_myAppWorkpd);
+
+ /* write output values of current cycle, by sending all cyclic frames */
+ PERF_JOB_START(JOB_SendAllCycFrames);
+ dwRes = ecatExecJob( eUsrJob_SendAllCycFrames, EC_NULL );
+ if (EC_E_NOERROR != dwRes && EC_E_INVALIDSTATE != dwRes && EC_E_LINK_DISCONNECTED != dwRes)
+ {
+ LogError("ecatExecJob( eUsrJob_SendAllCycFrames, EC_NULL ): %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ PERF_JOB_END(JOB_SendAllCycFrames);
+
+ /* remove this code when using licensed version */
+ if (EC_E_EVAL_EXPIRED == dwRes )
+ {
+ bRun = EC_FALSE; /* set shutdown flag */
+ }
+
+ /* Execute some administrative jobs. No bus traffic is performed by this function */
+ PERF_JOB_START(JOB_MasterTimer);
+ dwRes = ecatExecJob(eUsrJob_MasterTimer, EC_NULL);
+ if (EC_E_NOERROR != dwRes && EC_E_INVALIDSTATE != dwRes)
+ {
+ LogError("ecatExecJob(eUsrJob_MasterTimer, EC_NULL): %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ PERF_JOB_END(JOB_MasterTimer);
+
+ /* send queued acyclic EtherCAT frames */
+ PERF_JOB_START(JOB_SendAcycFrames);
+ dwRes = ecatExecJob(eUsrJob_SendAcycFrames, EC_NULL);
+ if (EC_E_NOERROR != dwRes && EC_E_INVALIDSTATE != dwRes && EC_E_LINK_DISCONNECTED != dwRes)
+ {
+ LogError("ecatExecJob(eUsrJob_SendAcycFrames, EC_NULL): %s (0x%lx)", ecatGetText(dwRes), dwRes);
+ }
+ PERF_JOB_END(JOB_SendAcycFrames);
+
+#if !(defined NO_OS)
+ } while (!pDemoThreadParam->bJobThreadShutdown);
+
+ PERF_MEASURE_JOBS_SHOW();
+
+ pDemoThreadParam->bJobThreadRunning = EC_FALSE;
+#else
+ /* in case of NO_OS the job task function is called cyclically within the timer ISR */
+ } while (EC_FALSE);
+ pDemoThreadParam->bJobThreadRunning = !pDemoThreadParam->bJobThreadShutdown;
+#endif
+
+Exit:
+#if (defined EC_VERSION_RTEMS)
+ rtems_task_delete(RTEMS_SELF);
+#endif
+ return;
+}
+
+/********************************************************************************/
+/** \brief Handler for master notifications
+*
+* \return Status value.
+*/
+static EC_T_DWORD ecatNotifyCallback(
+ EC_T_DWORD dwCode, /**< [in] Notification code */
+ EC_T_NOTIFYPARMS* pParms /**< [in] Notification parameters */
+ )
+{
+ EC_T_DWORD dwRetVal = EC_E_NOERROR;
+ CEmNotification* pNotifyInstance;
+
+ if ((EC_NULL == pParms)||(EC_NULL==pParms->pCallerData))
+ {
+ dwRetVal = EC_E_INVALIDPARM;
+ goto Exit;
+ }
+
+ /* notification for application ? */
+ if ((dwCode >= EC_NOTIFY_APP) && (dwCode <= EC_NOTIFY_APP+EC_NOTIFY_APP_MAX_CODE))
+ {
+ /*****************************************************/
+ /* Demo code: Remove/change this in your application */
+ /* to get here the API ecatNotifyApp(dwCode, pParms) has to be called */
+ /*****************************************************/
+ dwRetVal = myAppNotify(dwCode-EC_NOTIFY_APP, pParms);
+ }
+ else
+ {
+ pNotifyInstance = (CEmNotification*)pParms->pCallerData;
+
+ /* call the default handler */
+ dwRetVal = pNotifyInstance->ecatNotify(dwCode, pParms);
+ }
+
+Exit:
+ return dwRetVal;
+}
+
+
+/********************************************************************************/
+/** \brief Handler for master RAS notifications
+*
+*
+* \return Status value.
+*/
+#ifdef ATEMRAS_SERVER
+static EC_T_DWORD RasNotifyWrapper(
+ EC_T_DWORD dwCode,
+ EC_T_NOTIFYPARMS* pParms
+ )
+{
+ EC_T_DWORD dwRetVal = EC_E_NOERROR;
+ CEmNotification* pNotInst = EC_NULL;
+
+ if ((EC_NULL == pParms)||(EC_NULL==pParms->pCallerData))
+ {
+ dwRetVal = EC_E_INVALIDPARM;
+ goto Exit;
+ }
+
+ pNotInst = (CEmNotification*)(pParms->pCallerData);
+ dwRetVal = pNotInst->emRasNotify(dwCode, pParms);
+Exit:
+
+ return dwRetVal;
+}
+#endif
+
+/*-MYAPP---------------------------------------------------------------------*/
+#define MBX_TIMEOUT 5000
+
+#define EL4132_INDEX_USER_SCALE 0x40A2
+#define EL4132_SUBINDEX_USRSCL_NUMELEM 0
+#define EL4132_SUBINDEX_USRSCL_OFFSET 1
+#define EL4132_SUBINDEX_USRSCL_GAIN 2
+
+#define DEMO_MAX_NUM_OF_SLAVES 5
+#define SLAVE_NOT_FOUND 0xFFFF
+static EC_T_DWORD S_dwAppFoundSlaves = 0;
+static EC_T_CFG_SLAVE_INFO S_aSlaveList[DEMO_MAX_NUM_OF_SLAVES];
+static EC_T_DWORD S_dwSlaveIdx14 = SLAVE_NOT_FOUND;
+static EC_T_DWORD S_dwSlaveIdx24 = SLAVE_NOT_FOUND;
+static EC_T_DWORD S_dwSlaveIdx4132 = SLAVE_NOT_FOUND;
+static EC_T_DWORD S_dwSlaveIdxETCio100 = SLAVE_NOT_FOUND;
+
+/***************************************************************************************************/
+/**
+\brief Initialize Application
+
+\return EC_E_NOERROR on success, error code otherwise.
+*/
+static EC_T_DWORD myAppInit(
+ CAtEmLogging* poLog, /* [in] Logging instance */
+ EC_T_INT nVerbose /* [in] Verbosity level */
+ )
+{
+ EC_UNREFPARM(poLog);
+ EC_UNREFPARM(nVerbose);
+
+ S_dwAppFoundSlaves = 0;
+ OsMemset(S_aSlaveList, 0, DEMO_MAX_NUM_OF_SLAVES*sizeof(EC_T_CFG_SLAVE_INFO));
+ S_dwSlaveIdx14 = SLAVE_NOT_FOUND;
+ S_dwSlaveIdx24 = SLAVE_NOT_FOUND;
+ S_dwSlaveIdx4132 = SLAVE_NOT_FOUND;
+ S_dwSlaveIdxETCio100 = SLAVE_NOT_FOUND;
+
+ return EC_E_NOERROR;
+}
+
+/***************************************************************************************************/
+/**
+\brief Initialize Slave Instance.
+
+Find slave parameters.
+\return EC_E_NOERROR on success, error code otherwise.
+*/
+static EC_T_DWORD myAppPrepare(
+ CAtEmLogging* poLog, /* [in] Logging instance */
+ EC_T_INT nVerbose /* [in] Verbosity level */
+ )
+{
+EC_T_WORD wFixedAddress = 0;
+
+ EC_UNREFPARM(nVerbose);
+
+ /* Searching for: EL1004, EL1012, EL1014 */
+ /* search for the first device at the bus and return its fixed (EtherCAT) address */
+ if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL1004, &wFixedAddress))
+ {
+ S_dwSlaveIdx14 = S_dwAppFoundSlaves;
+ }
+ else if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL1012, &wFixedAddress))
+ {
+ S_dwSlaveIdx14 = S_dwAppFoundSlaves;
+ }
+ else if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL1014, &wFixedAddress))
+ {
+ S_dwSlaveIdx14 = S_dwAppFoundSlaves;
+ }
+ if (S_dwSlaveIdx14 != SLAVE_NOT_FOUND)
+ {
+ S_dwAppFoundSlaves++;
+
+ /* now get the offset of this device in the process data buffer and some other infos */
+ if (ecatGetCfgSlaveInfo(EC_TRUE, wFixedAddress, &S_aSlaveList[S_dwSlaveIdx14]) != EC_E_NOERROR)
+ {
+ LogError("ERROR: ecatGetCfgSlaveInfo() returns with error.");
+ }
+ }
+ /* Searching for: EL2002, EL2004, EL2008 */
+ /* search for the first device at the bus and return its fixed (EtherCAT) address */
+ if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL2008, &wFixedAddress))
+ {
+ S_dwSlaveIdx24 = S_dwAppFoundSlaves;
+ }
+ else if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL2004, &wFixedAddress))
+ {
+ S_dwSlaveIdx24 = S_dwAppFoundSlaves;
+ }
+ else if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL2002, &wFixedAddress))
+ {
+ S_dwSlaveIdx24 = S_dwAppFoundSlaves;
+ }
+ if (S_dwSlaveIdx24 != SLAVE_NOT_FOUND)
+ {
+ S_dwAppFoundSlaves++;
+
+ /* now get the offset of this device in the process data buffer and some other infos */
+ if (ecatGetCfgSlaveInfo(EC_TRUE, wFixedAddress, &S_aSlaveList[S_dwSlaveIdx24]) != EC_E_NOERROR)
+ {
+ LogError("ERROR: ecatGetCfgSlaveInfo() returns with error.");
+ }
+ }
+
+ /* Searching for: EL4132 */
+ /* search for the first device at the bus and return its fixed (EtherCAT) address */
+ if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_beckhoff, ecprodcode_beck_EL4132, &wFixedAddress))
+ {
+ S_dwSlaveIdx4132 = S_dwAppFoundSlaves;
+ S_dwAppFoundSlaves++;
+ /* now get the offset of this device in the process data buffer and some other infos */
+ if (ecatGetCfgSlaveInfo(EC_TRUE, wFixedAddress, &S_aSlaveList[S_dwSlaveIdx4132]) != EC_E_NOERROR)
+ {
+ LogError("ERROR: ecatGetCfgSlaveInfo() returns with error.");
+ }
+ }
+ /* Searching for: IXXAT ETCio100 */
+ /* search for the first device at the bus and return its fixed (EtherCAT) address */
+ if (FindSlaveGetFixedAddr(INSTANCE_MASTER_DEFAULT, poLog, 0, ecvendor_ixxat, ecprodcode_ixx_ETCio100, &wFixedAddress))
+ {
+ S_dwSlaveIdxETCio100 = S_dwAppFoundSlaves;
+ S_dwAppFoundSlaves++;
+ /* now get the offset of this device in the process data buffer and some other infos */
+ if (ecatGetCfgSlaveInfo(EC_TRUE, wFixedAddress, &S_aSlaveList[S_dwSlaveIdxETCio100]) != EC_E_NOERROR)
+ {
+ LogError("ERROR: ecatGetCfgSlaveInfo() returns with error.");
+ }
+ }
+ return EC_E_NOERROR;
+}
+
+/***************************************************************************************************/
+/**
+\brief Setup slave parameters (normally done in PREOP state
+
+ - SDO up- and Downloads
+ - Read Object Dictionary
+
+\return EC_E_NOERROR on success, error code otherwise.
+*/
+static EC_T_DWORD myAppSetup(
+ CAtEmLogging* poLog, /* [in] Logging instance */
+ EC_T_INT nVerbose, /* [in] verbosity level */
+ EC_T_DWORD dwClntId /* [in] EtherCAT master client id */
+ )
+{
+ EC_T_DWORD dwRes = EC_E_ERROR;
+ EC_T_CFG_SLAVE_INFO* pMySlave = EC_NULL;
+
+ if (S_dwSlaveIdx4132 != SLAVE_NOT_FOUND)
+ {
+ EC_T_BOOL bStopReading = EC_FALSE; /* Flag to stop object dictionary reading */
+ EC_T_BYTE byNumElements;
+ EC_T_DWORD dwSize;
+ EC_T_WORD wOffsetTmp = 0;
+ EC_T_DWORD dwGainTmp = 0;
+ EC_T_WORD wOffset;
+ EC_T_DWORD dwGain;
+
+ pMySlave = &S_aSlaveList[S_dwSlaveIdx4132];
+
+ /* demo: simple CoE SDO upload */
+ /* - synchronous: block until upload has finished */
+ dwRes = ecatCoeSdoUpload(pMySlave->dwSlaveId, EL4132_INDEX_USER_SCALE, EL4132_SUBINDEX_USRSCL_NUMELEM,
+ &byNumElements, sizeof(EC_T_BYTE), &dwSize, MBX_TIMEOUT, 0);
+
+ if (dwRes == EC_E_NOERROR)
+ {
+ if (nVerbose >= 2) LogMsg("tEl4132Mbx: EL4132 user scale: num elements = %d", (int)byNumElements);
+ }
+ else
+ {
+ LogError("tEl4132Mbx: error in COE SDO Upload! %s (0x%x)", ecatGetText(dwRes), dwRes);
+ }
+
+ dwRes = ecatCoeSdoUpload(pMySlave->dwSlaveId, EL4132_INDEX_USER_SCALE, EL4132_SUBINDEX_USRSCL_OFFSET,
+ (EC_T_BYTE*)&wOffsetTmp, sizeof(EC_T_WORD), &dwSize, MBX_TIMEOUT, 0);
+ wOffset = EC_NTOHS(wOffsetTmp);
+
+ if (dwRes == EC_E_NOERROR)
+ {
+ if (nVerbose >= 2) LogMsg("tEl4132Mbx: EL4132 offset = 0x%x", (EC_T_DWORD)wOffset);
+ }
+ else
+ {
+ LogError("tEl4132Mbx: error in COE SDO Upload! %s (0x%x)", ecatGetText(dwRes), dwRes);
+ }
+
+ dwRes = ecatCoeSdoUpload(pMySlave->dwSlaveId, EL4132_INDEX_USER_SCALE, EL4132_SUBINDEX_USRSCL_GAIN,
+ (EC_T_BYTE*)&dwGainTmp, sizeof(EC_T_DWORD), &dwSize, MBX_TIMEOUT, 0);
+ dwGain = EC_NTOHL(dwGainTmp);
+
+ if (dwRes == EC_E_NOERROR)
+ {
+ if (nVerbose >= 2) LogMsg("tEl4132Mbx: EL4132 gain = 0x%x", dwGain);
+ }
+ else
+ {
+ LogError("tEl4132Mbx: error in COE SDO Upload! %s (0x%x)", ecatGetText(dwRes), dwRes);
+ }
+
+ /* demo: simple CoE SDO download */
+ /* - synchronous: block until download has finished */
+ wOffset++; /* change user scale offset value */
+ if (wOffset > 0x1000)
+ {
+ wOffset = 0;
+ }
+ wOffsetTmp = EC_HTONS(wOffset);
+ dwRes = ecatCoeSdoDownload(pMySlave->dwSlaveId, EL4132_INDEX_USER_SCALE, EL4132_SUBINDEX_USRSCL_OFFSET,
+ (EC_T_BYTE*)&wOffsetTmp, sizeof(EC_T_WORD), MBX_TIMEOUT, 0);
+
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("tEl4132Mbx: error in COE SDO Download! %s (0x%x)", ecatGetText(dwRes), dwRes);
+ }
+ dwGain += 0x1000;
+ if (dwGain > 0x10000000)
+ {
+ dwGain = 0;
+ }
+
+ dwGainTmp = EC_HTONL(dwGain);
+ dwRes = ecatCoeSdoDownload(pMySlave->dwSlaveId, EL4132_INDEX_USER_SCALE, EL4132_SUBINDEX_USRSCL_GAIN,
+ (EC_T_BYTE*)&dwGainTmp, sizeof(EC_T_DWORD), MBX_TIMEOUT, 0);
+
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("tEl4132Mbx: error in COE SDO Download! %s (0x%x)", ecatGetText(dwRes), dwRes);
+ }
+
+ /* now read object dict */
+ /* In a real application this is typically not necessary */
+ dwRes = CoeReadObjectDictionary(INSTANCE_MASTER_DEFAULT, poLog, nVerbose, &bStopReading, dwClntId, pMySlave->dwSlaveId, EC_TRUE, MBX_TIMEOUT);
+ }
+ return EC_E_NOERROR;
+}
+
+/***************************************************************************************************/
+/**
+\brief demo application working process data function.
+
+ This function is called in every cycle after the the master stack is started.
+
+*/
+static EC_T_DWORD myAppWorkpd(
+ CAtEmLogging* poLog, /* [in] Logging instance */
+ EC_T_INT nVerbose, /* [in] Verbosity level */
+ EC_T_BYTE* pbyPDIn, /* [in] pointer to process data input buffer */
+ EC_T_BYTE* pbyPDOut /* [in] pointer to process data output buffer */
+ )
+{
+ EC_T_CFG_SLAVE_INFO* pMySlave = EC_NULL;
+
+ static EC_T_DWORD s_dwWorkpdCnt = 0;
+ EC_T_BYTE byVal = 0;
+ EC_T_BYTE* pbyVal = EC_NULL;
+ EC_T_WORD* pwVal = EC_NULL;
+ EC_T_WORD wValue = 0;
+
+ EC_UNREFPARM(poLog);
+ EC_UNREFPARM(nVerbose);
+
+ /* process data are not modified not every cycle */
+ s_dwWorkpdCnt++;
+ if ((s_dwWorkpdCnt % 100) != 0)
+ {
+ goto Exit;
+ }
+ /* Digital input slave available ? */
+ if ((S_dwSlaveIdx14 != SLAVE_NOT_FOUND) && (pbyPDIn != EC_NULL))
+ {
+ static EC_T_BYTE s_byDigInputLastVal = 0;
+
+ /* get slave information */
+ pMySlave = &S_aSlaveList[S_dwSlaveIdx14];
+
+ /* monitor input change if ENI was NOT generated with GenPreopENI */
+ if (((EC_T_DWORD)-1) != pMySlave->dwPdOffsIn)
+ {
+ EC_GETBITS(pbyPDIn, &byVal, pMySlave->dwPdOffsIn, pMySlave->dwPdSizeIn);
+ if (byVal != s_byDigInputLastVal)
+ {
+ if (nVerbose >= 2)
+ {
+ LogMsg("Input Value updated : Old : 0x%x -> New : 0x%x", s_byDigInputLastVal, byVal);
+ s_byDigInputLastVal = byVal;
+ }
+ }
+ }
+ }
+ /* Digital output device */
+ if ((S_dwSlaveIdx24 != SLAVE_NOT_FOUND) && (pbyPDOut != EC_NULL))
+ {
+ /* get slave information */
+ pMySlave = &S_aSlaveList[S_dwSlaveIdx24];
+
+ /* flash output if ENI was NOT generated with GenPreopENI */
+ if (((EC_T_DWORD)-1) != pMySlave->dwPdOffsOut)
+ {
+ EC_GETBITS(pbyPDOut, &byVal, pMySlave->dwPdOffsOut, pMySlave->dwPdSizeOut);
+ byVal++;
+ EC_SETBITS(pbyPDOut, &byVal, pMySlave->dwPdOffsOut, pMySlave->dwPdSizeOut);
+ }
+ }
+
+ /* EL4132 */
+ if ((S_dwSlaveIdx4132 != SLAVE_NOT_FOUND) && (pbyPDOut != EC_NULL))
+ {
+ /* get slave information */
+ pMySlave = &S_aSlaveList[S_dwSlaveIdx4132];
+
+ /* do some upcounting on channel 1 */
+ if (((EC_T_DWORD)-1) != pMySlave->dwPdOffsOut)
+ {
+ pwVal = (EC_T_WORD*)&pbyPDOut[pMySlave->dwPdOffsOut/8];
+ wValue = EC_GET_FRM_WORD(pwVal); /* for big endian systems we have to swap */
+ wValue++;
+ EC_SET_FRM_WORD(pwVal, wValue);
+
+ /* do some downcounting on channel 2 */
+ pwVal = (EC_T_WORD*)&pbyPDOut[(pMySlave->dwPdOffsOut+16)/8];
+ wValue = EC_GET_FRM_WORD(pwVal); /* for big endian systems we have to swap */
+ wValue--;
+ EC_SET_FRM_WORD(pwVal, wValue);
+ }
+ }
+ /* IXXAT ETCio100 */
+ if ((S_dwSlaveIdxETCio100 != SLAVE_NOT_FOUND) && (pbyPDOut != EC_NULL))
+ {
+ /* get slave information */
+ pMySlave = &S_aSlaveList[S_dwSlaveIdxETCio100];
+
+ /* flash digital output if ENI was NOT generated with GenPreopENI */
+ if (((EC_T_DWORD)-1) != pMySlave->dwPdOffsOut)
+ {
+ pbyVal = (EC_T_BYTE*)&pbyPDOut[pMySlave->dwPdOffsOut/8];
+ *pbyVal = (EC_T_BYTE)((*pbyVal) + 1);
+ }
+
+ /* increase analog output 1 if ENI was NOT generated with GenPreopENI */
+ /* analog outputs are 12 Bit values at the ETCio 100 */
+ if (((EC_T_DWORD)-1) != pMySlave->dwPdOffsOut)
+ {
+ pwVal = (EC_T_WORD*)&pbyPDOut[(pMySlave->dwPdOffsOut+8)/8];
+ wValue = EC_GET_FRM_WORD(pwVal); /* for big endian systems we have to swap */
+ wValue = (EC_T_WORD)(wValue + 0x100); /* to get a well measurable value difference modify last value by 0x100 */
+ if(wValue & 0xF000) /* 12 Bit value. The 4 highest bits are not relevant for the analog value */
+ {
+ wValue = 0;
+ }
+ EC_SET_FRM_WORD(pwVal, wValue);
+ }
+
+ /* decrease analog output 2 if ENI was NOT generated with GenPreopENI */
+ /* analog outputs are 12 Bit values at the ETCio 100 */
+ if (((EC_T_DWORD)-1) != pMySlave->dwPdOffsOut)
+ {
+ pwVal = (EC_T_WORD*)&pbyPDOut[(pMySlave->dwPdOffsOut+24)/8];
+ wValue = EC_GET_FRM_WORD(pwVal); /* for big endian systems we have to swap */
+ wValue = (EC_T_WORD)(wValue - 0x100); /* to get a well measurable value difference modify last value by 0x100 */
+ if(wValue & 0xF000) /* 12 Bit value. The 4 highest bits are not relevant for the analog value */
+ {
+ wValue = 0x0F00;
+ }
+ EC_SET_FRM_WORD(pwVal, wValue);
+ }
+ }
+
+Exit:
+ return EC_E_NOERROR;
+}
+
+/***************************************************************************************************/
+/**
+\brief demo application doing some diagnostic tasks
+
+ This function is called in sometimes from the main demo task
+*/
+static EC_T_DWORD myAppDiagnosis(
+ CAtEmLogging* poLog, /* [in] Logging instance */
+ EC_T_INT nVerbose /* [in] Verbosity level */
+ )
+{
+ EC_T_DWORD dwRes = EC_E_ERROR;
+ EC_T_CFG_SLAVE_INFO* pMySlave = EC_NULL;
+
+ EC_UNREFPARM(poLog);
+ EC_UNREFPARM(nVerbose);
+
+ if (S_dwSlaveIdx4132 != SLAVE_NOT_FOUND)
+ {
+ EC_T_DWORD dwSize = 0;
+ EC_T_DWORD dwValue = 0;
+
+ pMySlave = &S_aSlaveList[S_dwSlaveIdx4132];
+
+ dwRes = ecatCoeSdoUpload(pMySlave->dwSlaveId, 0x1018, 1,
+ (EC_T_BYTE*)&dwValue, sizeof(EC_T_DWORD), &dwSize, MBX_TIMEOUT, 0);
+
+ if (dwRes != EC_E_NOERROR)
+ {
+ LogError("myAppDiagnosis: error in COE SDO Upload of object 0x1018! %s (0x%x)", ecatGetText(dwRes), dwRes);
+ }
+ }
+
+ return EC_E_NOERROR;
+}
+
+/********************************************************************************/
+/** \brief Handler for application notifications
+*
+* !!! No blocking API shall be called within this function!!!
+* !!! Function is called by cylic task !!!
+*
+* \return Status value.
+*/
+static EC_T_DWORD myAppNotify(
+ EC_T_DWORD dwCode, /* [in] Application notification code */
+ EC_T_NOTIFYPARMS* pParms /* [in] Notification parameters */
+ )
+{
+ EC_T_DWORD dwRetVal = EC_E_ERROR;
+
+ EC_UNREFPARM(pParms);
+
+ /* dispatch notification code */
+ switch(dwCode)
+ {
+ case 1:
+ LogMsg("Application notification code=%d received\n", dwCode);
+ /* dwRetVal = EC_E_NOERROR; */
+ break;
+ case 2:
+ break;
+ default:
+ break;
+ }
+
+ return dwRetVal;
+}
+
+/*-END OF SOURCE FILE--------------------------------------------------------*/
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemo.h b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemo.h
--- /dev/null
@@ -0,0 +1,66 @@
+/*-----------------------------------------------------------------------------
+ * ATEMDemo.h
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description EtherCAT Master demo header
+ *---------------------------------------------------------------------------*/
+
+/*-INCLUDES------------------------------------------------------------------*/
+#include "ATEMDemoConfig.h"
+#include "ecatNotification.h"
+#include "ecatDemoCommon.h"
+#ifdef VXWORKS
+#include "wvLib.h"
+#endif
+
+/*-MACROS--------------------------------------------------------------------*/
+
+/*-DEFINES-------------------------------------------------------------------*/
+#define MAX_LINKLAYER 5
+
+#if (defined EC_SOCKET_SUPPORTED)
+/* the RAS server is necessary to support the EC-Engineer or other remote applications */
+ #define ATEMRAS_SERVER
+#endif
+#define REMOTE_WD_TO_LIMIT 10000
+#define REMOTE_CYCLE_TIME 2
+
+/*-FORWARD DECLARATIONS------------------------------------------------------*/
+EC_T_DWORD ATEMDemo(
+ CAtEmLogging* poLog
+ ,EC_T_CNF_TYPE eCnfType
+ ,EC_T_PBYTE pbyCnfData
+ ,EC_T_DWORD dwCnfDataLen
+ ,EC_T_DWORD dwBusCycleTimeUsec
+ ,EC_T_INT nVerbose
+ ,EC_T_DWORD dwDuration
+ ,EC_T_LINK_PARMS* poLinkParms
+ ,EC_T_VOID* pvTimingEvent
+ ,EC_T_DWORD dwCpuIndex
+ ,EC_T_BOOL bEnaPerfJobs
+#ifdef ATEMRAS_SERVER
+ ,EC_T_WORD wServerPort
+#endif
+ ,EC_T_LINK_PARMS* poLinkParmsRed
+ );
+
+/*--------------------------------------------------------------------------*/
+/* Performance measurements of jobs */
+/* This is only available on CPUs with TSC support */
+/*--------------------------------------------------------------------------*/
+
+#define JOB_ProcessAllRxFrames 0
+#define JOB_SendAllCycFrames 1
+#define JOB_MasterTimer 2
+#define JOB_SendAcycFrames 3
+#define PERF_CycleTime 4
+#define PERF_myAppWorkpd 5
+#define MAX_JOB_NUM 6
+
+#define PERF_MEASURE_JOBS_INIT(msgcb) ecatPerfMeasInit(&S_TscMeasDesc,0,MAX_JOB_NUM,msgcb);ecatPerfMeasEnable(&S_TscMeasDesc)
+#define PERF_MEASURE_JOBS_DEINIT() ecatPerfMeasDeinit(&S_TscMeasDesc)
+#define PERF_MEASURE_JOBS_SHOW() ecatPerfMeasShow(&S_TscMeasDesc,0xFFFFFFFF,S_aszMeasInfo)
+#define PERF_JOB_START(nJobIndex) ecatPerfMeasStart(&S_TscMeasDesc,(EC_T_DWORD)(nJobIndex))
+#define PERF_JOB_END(nJobIndex) ecatPerfMeasEnd(&S_TscMeasDesc,(EC_T_DWORD)(nJobIndex))
+
+/*-END OF SOURCE FILE--------------------------------------------------------*/
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemoConfig.h b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemoConfig.h
--- /dev/null
@@ -0,0 +1,214 @@
+/*-----------------------------------------------------------------------------
+ * ATEMDemoConfig.h
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description EtherCAT Master demo configuration header
+ *---------------------------------------------------------------------------*/
+
+/*-INCLUDES------------------------------------------------------------------*/
+
+
+/*-DEFINES-------------------------------------------------------------------*/
+
+/*********************/
+/* thread priorities */
+/*********************/
+#if defined WIN32 && !defined UNDER_CE && !defined RTOS_32 && !defined UNDER_RTSS
+ /* we need to set all threads to the highest possible priority to avoid errors! */
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)THREAD_PRIORITY_TIME_CRITICAL) /* EtherCAT master trigger thread priority */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)THREAD_PRIORITY_TIME_CRITICAL) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)THREAD_PRIORITY_TIME_CRITICAL) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)THREAD_PRIORITY_LOWEST) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)THREAD_PRIORITY_NORMAL)
+#elif (defined UNDER_RTSS)
+ #define TIMER_THREAD_PRIO (RT_PRIORITY_MAX-0) /* EtherCAT master trigger thread priority */
+ #define JOBS_THREAD_PRIO (RT_PRIORITY_MAX-1) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO (RT_PRIORITY_MAX-2) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO (RT_PRIORITY_MIN) /* EtherCAT message logging thread priority */
+ #define LOG_ROLLOVER ((EC_T_WORD)0) /* EtherCAT message logging rollover counter limit */
+ #define MAIN_THREAD_PRIO (RT_PRIORITY_MIN)
+ #define JOBS_THREAD_STACKSIZE 0x8000
+ #define LOG_THREAD_STACKSIZE 0x8000
+#elif (defined RTOS_32)
+ #define MAIN_THREAD_PRIO_OFFSET 10
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)64) /* EtherCAT master trigger thread priority */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)63) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)62) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)1 ) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)3+MAIN_THREAD_PRIO_OFFSET)
+#elif (defined QNX6)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)100) /* EtherCAT master trigger thread priority */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)99) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)98) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)40) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)30)
+ #define REMOTE_RECV_THREAD_PRIO ((EC_T_DWORD)50) /* slightly higher than logger */
+#elif (defined __RCX__)
+ #define REALTIME_PRIORITY_OFFSET TSK_PRIO_2
+ #define MAIN_THREAD_PRIO_OFFSET TSK_PRIO_50
+ #define TIMER_THREAD_PRIO (0+REALTIME_PRIORITY_OFFSET) /* EtherCAT master trigger thread priority */
+ #define JOBS_THREAD_PRIO (1+REALTIME_PRIORITY_OFFSET) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO (2+REALTIME_PRIORITY_OFFSET) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO (5+MAIN_THREAD_PRIO_OFFSET) /* EtherCAT message logging thread priority */
+ #define LOG_ROLLOVER ((EC_T_WORD)0) /* EtherCAT message logging rollover counter limit */
+ #define MAIN_THREAD_PRIO (MAIN_THREAD_PRIO_OFFSET)
+#elif (defined RTAI)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)99) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)5) /* EtherCAT master job thread priority (tEcJobTask) */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)99) /* EtherCAT master packet receive thread priority (tLOsaL_IST) */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)99) /* EtherCAT message logging thread priority (tAtEmLog) */
+#elif (defined LINUX)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)99) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)98) /* EtherCAT master job thread priority (tEcJobTask) */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)97) /* EtherCAT master packet receive thread priority (tLOsaL_IST) */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)29) /* EtherCAT message logging thread priority (tAtEmLog) */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)39) /* Main thread */
+#elif (defined __INTEGRITY)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)200) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)199) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)198) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)40) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)40)
+#elif (defined __INTIME__)
+ /*Priority 0 to 127 Used by the OS for servicing external interrupts. */
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)128) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)129) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)0) /* Is not used for INtime. The receive thread priority is defined by the Interrupt Level */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)200) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)130)
+#elif (defined __TKERNEL)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)1) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)2) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)4) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)10)
+#elif (defined EC_VERSION_SYSBIOS)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)12) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)12) /* EtherCAT master job thread priority (tEcJobTask) */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)12) /* EtherCAT master packet receive thread priority (tLOsaL_IST) */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)1) /* EtherCAT message logging thread priority (tAtEmLog) */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)2) /* Main thread */
+ #if defined SOC_AM572x
+ #if defined LINKLAYER_ICSS
+ #define DEMO_PARAMETERS "-auxclk 2000 -v 2 -t 10000 -perf " \
+ "-icss " \
+ "2 " /* Instance 1 or 2*/ \
+ "1 " /* mode */ \
+ "0" /* Eth port 0 or 1 */ //PC-- for AM572x IDK "0" = PRU2ETH0 (J6) and "1" = PRU2ETH1 (J8)
+ #else
+ #define DEMO_PARAMETERS "-auxclk 2000 -v 2 -t 10000 -perf " \
+ "-cpsw " \
+ "1 " /* port PC-- Only tested on port=2. for AM572x IDK "1" = ETH0 (J10) and "2" = ETH1 (J12) */ \
+ "1 " /* mode */ \
+ "1 " /* priority */ \
+ "m " /* master flag */ \
+ "am572x-idk " /* reference board */
+ #endif
+ #else
+ #define DEMO_PARAMETERS "-auxclk 2000 -v 2 -t 10000 -perf " \
+ "-cpsw " \
+ "1 " /* port PC-- for AM572x IDK "0" = ETH0 (J10) and "1" = ETH1 (J12) */ \
+ "1 " /* mode */ \
+ "1 " /* priority */ \
+ "m " /* master flag */ \
+ "custom am33XX " /* custom board for AM33xx*/ \
+ "1 " /* PHY address */ \
+ "1 " /* PHY connection mode: RGMII */ \
+ "0 " /* Not use DMA buffers */
+ #endif /* SOC_AM57x */
+
+#elif (defined EC_VERSION_RIN32M3)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master job thread priority (tEcJobTask) */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master packet receive thread priority (tLOsaL_IST) */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)14) /* EtherCAT message logging thread priority (tAtEmLog) */
+ #define DEMO_PARAMETERS "-auxclk 1000 -t 0 -v 2 -perf -rin32m3"
+#elif (defined EC_VERSION_XILINX_STANDALONE)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master job thread priority (tEcJobTask) */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master packet receive thread priority (tLOsaL_IST) */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)14) /* EtherCAT message logging thread priority (tAtEmLog) */
+ #define DEMO_PARAMETERS "-auxclk 1000 -v 2 -t 10000 -perf -rin32m3"
+#elif (defined EC_VERSION_ETKERNEL)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)1) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)2) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)4) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)10)
+ #define DEMO_PARAMETERS "-b 2000 -fslfec 1 1 sabresd -v 2 -t 10000 -perf"
+#elif (defined EC_VERSION_RZT1)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)1) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)2) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)4) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)10)
+ #define DEMO_PARAMETERS "-rzt1 1 -v 2 -t 20000 -perf -auxclk 1000"
+ #define LOG_THREAD_STACKSIZE 0x2000
+#elif (defined EC_VERSION_RZGNOOS)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)1) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)2) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)4) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO ((EC_T_DWORD)10)
+ #define DEMO_PARAMETERS "-sheth 1 1 rzg1e -v 3 -t 20000 -perf -auxclk 1000"
+ #define LOG_THREAD_STACKSIZE 0x2000
+#elif (defined EC_VERSION_ECOS)
+ #define TIMER_THREAD_PRIO ((EC_T_DWORD)1) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO ((EC_T_DWORD)2) /* EtherCAT master job thread priority */
+ #define RECV_THREAD_PRIO ((EC_T_DWORD)3) /* EtherCAT master interrupt service thread priority */
+ #define LOG_THREAD_PRIO ((EC_T_DWORD)4) /* EtherCAT message logging thread priority */
+#else
+
+ #ifdef VXWORKS_NORMAL_PRIO
+ #define REALTIME_PRIORITY_OFFSET 60
+ #else
+ #define REALTIME_PRIORITY_OFFSET 2
+ #endif
+
+ #define TIMER_THREAD_PRIO (0+REALTIME_PRIORITY_OFFSET) /* EtherCAT master timer task (tEcTimingTask) */
+ #define JOBS_THREAD_PRIO (1+REALTIME_PRIORITY_OFFSET) /* EtherCAT master cyclic packet send thread priority */
+ #define RECV_THREAD_PRIO (2+REALTIME_PRIORITY_OFFSET) /* EtherCAT master packet receive thread priority */
+ #define MBX_THREAD_PRIO (3+REALTIME_PRIORITY_OFFSET) /* mailbox demo thread priority */
+
+ #define LOG_THREAD_PRIO (200) /* EtherCAT message logging thread priority */
+ #define MAIN_THREAD_PRIO (4+REALTIME_PRIORITY_OFFSET)
+ #define REMOTE_RECV_THREAD_PRIO 0
+
+#endif
+#ifndef TIMER_THREAD_STACKSIZE
+#define TIMER_THREAD_STACKSIZE 0x1000
+#endif
+#ifndef JOBS_THREAD_STACKSIZE
+#define JOBS_THREAD_STACKSIZE 0x4000
+#endif
+#ifndef LOG_THREAD_STACKSIZE
+#define LOG_THREAD_STACKSIZE 0x4000
+#endif
+
+/******************/
+/* timer settings */
+/******************/
+#define CYCLE_TIME 1 /* 1 msec */
+#define BASE_PERIOD 1000 /* 1000 usec */
+
+/***********************************************/
+/* static EtherCAT master configuration values */
+/***********************************************/
+#define MASTER_CFG_ECAT_CMD_MAX_RETRIES 5 /* maximum retries to send pending ethercat command frames */
+
+#define MASTER_CFG_EOE_TIMEOUT 1000 /* timeout sending EoE frames */
+#define MASTER_CFG_FOE_BUSY_TIMEOUT 250 /* timeout FoE busy */
+
+#if !(defined EC_DEMO_TINY)
+#define MASTER_CFG_MAX_QUEUED_ETH_FRAMES 32 /* max number of queued frames, 127 = the absolute maximum number */
+#define MASTER_CFG_MAX_SENT_QUFRM_PER_CYC 3 /* max number of queued frames sent with eUsrJob_SendAcycFrames within one cycle */
+#define MASTER_CFG_MAX_SLAVECMD_PER_FRAME 32 /* max number of ecat telegrams per frame (0=maximum possible) */
+#define MASTER_CFG_ECAT_MAX_BUS_SLAVES 256 /* max number of pre-allocated bus slave objects */
+#else /* EC_DEMO_TINY */
+#define MASTER_CFG_MAX_QUEUED_ETH_FRAMES 12 /* max number of queued frames, 127 = the absolute maximum number */
+#define MASTER_CFG_MAX_SENT_QUFRM_PER_CYC 1 /* max number of queued frames sent with eUsrJob_SendAcycFrames within one cycle */
+#define MASTER_CFG_MAX_SLAVECMD_PER_FRAME 3 /* max number of ecat telegrams per frame (0=maximum possible) */
+#define MASTER_CFG_ECAT_MAX_BUS_SLAVES 8 /* max number of pre-allocated bus slave objects */
+#endif /* EC_DEMO_TINY */
+
+/*-END OF SOURCE FILE--------------------------------------------------------*/
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemoMain.cpp b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/ATEMDemoMain.cpp
--- /dev/null
@@ -0,0 +1,1908 @@
+/*-----------------------------------------------------------------------------
+ * ATEMDemoMain.cpp
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description EtherCAT Master demo main entrypoint
+ *---------------------------------------------------------------------------*/
+
+/*-INCLUDES------------------------------------------------------------------*/
+#include <AtEthercat.h>
+#include <EcCommon.h>
+
+#include "ATEMDemo.h"
+#include "selectLinkLayer.h"
+#include "Logging.h"
+
+#if (defined ATEMRAS_SERVER)
+#include <AtEmRasSrv.h>
+#endif
+
+#if (defined WIN32)
+ #if (defined UNDER_CE)
+ #include "pkfuncs.h"
+ #include "nkintr.h"
+ #if (_WIN32_WCE >= 0x600)
+ #if (defined ECWIN_CE)
+ #include <CeWin.h>
+ #include <RtosLib.h>
+ #else
+ #include <AuxClk.h>
+ #endif
+ #include <VirtIO.h>
+ #endif
+
+ #elif (defined RTOS_32)
+ #ifdef ECWIN_RTOS32
+ #include <Rtvmf.h>
+ #include <rtk32.h>
+ /* STRICT and _CRT_SECURE_NO_WARNINGS will be set again by Rteos.h included by vmfInterface.h */
+ #if !(defined _RTEOS_H)
+ #undef STRICT
+ #undef _CRT_SECURE_NO_WARNINGS
+ #endif /* !_RTEOS_H */
+ #include <vmfInterface.h>
+ #include <RtosLib.h>
+ #include <RtosLibFs.h>
+
+ /* IP Sockets are always reference by EC-Master for RTOS-32. Link IP stack if available or stubs. */
+ #ifdef EC_SOCKET_IP_SUPPORTED
+ #pragma comment(lib, "Rtip.lib")
+ #pragma comment(lib, "Netvmf.lib")
+ #else
+ #include <RtipDummy.cpp>
+ #endif /* EC_SOCKET_IP_SUPPORTED */
+ #else
+ #include <rttarget.h>
+ #include <rtk32.h>
+ #include <clock.h>
+ #include <timer.h>
+ #endif
+ #if (defined ATEMRAS_SERVER) && (defined EC_SOCKET_IP_SUPPORTED) && (defined INCLUDE_RTIP)
+ #include <NetRTOS32Init.cpp>
+ #endif
+ #else /* WINDOWS, RTX, ... */
+ #include <warn_dis.h>
+ #include <windows.h>
+ #include <tchar.h>
+ #include <warn_ena.h>
+ #endif
+#endif /* WIN32 */
+
+#if (defined VXWORKS)
+ #include <vxWorks.h>
+ #include <sysLib.h>
+ #include <tickLib.h>
+#if ((defined _WRS_VXWORKS_MAJOR) && (defined _WRS_VXWORKS_MINOR) && ( (_WRS_VXWORKS_MAJOR >= 7) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 5)) ))
+#else
+ #include <ifLib.h>
+#endif
+#endif /* VXWORKS */
+
+#if (defined LINUX)
+ #include <sys/mman.h>
+ #include <sys/utsname.h>
+ #include <signal.h>
+#endif /* LINUX */
+
+#if defined __INTEGRITY
+ #include <unistd.h>
+#endif
+
+#if (defined __RCX__)
+ #include "tlr_includes.h" /* TLR includes */
+ #include "AtemDemo_Functionlist.h"
+#endif
+
+#if (defined EC_VERSION_GO32)
+#include <dmpcfg.h>
+#include <io.h>
+#include <irq.h>
+#endif
+
+#if (defined EC_VERSION_RTEMS)
+#include <rtems.h>
+#include <rtems/bdpart.h>
+#include <rtems/fsmount.h>
+#include <rtems/monitor.h>
+#include <rtems/blkdev.h>
+#include <rtems/tod.h>
+#include "RtemsConf.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if (defined XENOMAI)
+#include <execinfo.h> /* for backtracing functions */
+#endif
+
+/*-DEFINES-------------------------------------------------------------------*/
+
+#define LogMsg oLogging.LogMsg
+#define LogError oLogging.LogError
+
+#define COMMAND_LINE_BUFFER_LENGTH 512
+
+#if !defined(ATECAT_DLL)
+/* For operating systems don't supporting dynamic libraries, the link layers */
+/* are linked statically to the application. Select the link layer(s) here */
+#if (defined RTAI)
+ #define LINKLAYER_I8254X
+#endif
+#if (defined RTOS_32) || (defined __INTEGRITY) || (defined __TKERNEL)
+ #define LINKLAYER_I8254X
+//#define LINKLAYER_I8255X
+//#define LINKLAYER_RTL8139
+//#define LINKLAYER_RTL8169
+#endif
+#if (defined ECWIN_RTOS32)
+/* all link layers are available */
+ #define LINKLAYER_I8255X
+ #define LINKLAYER_RTL8139
+ #define LINKLAYER_RTL8169
+#endif
+#if (defined __RCX__)
+ #define LINKLAYER_HNX
+#endif
+#if (defined EC_VERSION_ETKERNEL)
+ #define LINKLAYER_FSLFEC
+#endif
+#if (defined EC_VERSION_SYSBIOS)
+ #define LINKLAYER_CPSW
+#endif /* EC_VERSION_SYSBIOS */
+#if (defined EC_VERSION_RTEMS)
+//#define RTEMS_USE_TIMER_SERVER
+ #define LINKLAYER_I8254X
+ #define LINKLAYER_RTL8169
+ #define LINKLAYER_CCAT
+#endif /* EC_VERSION_RTEMS */
+
+#if (defined EC_VERSION_ECOS)
+ #define LINKLAYER_I8254X
+#endif /* EC_VERSION_ECOS */
+
+#endif /* !ATECAT_DLL */
+
+#if (defined RTAI)
+extern "C" long int G_dwBusCycleTimeUsec;
+/** created from MasterENI.xml with "objcopy -B i386 -I binary -O elf32-i386 MasterENI.xml MasterENI.o" */
+extern EC_T_BYTE MasterENI_xml_data[] asm("_binary_MasterENI_xml_start");
+extern EC_T_BYTE MasterENI_xml_data_size[] asm("_binary_MasterENI_xml_size");
+extern EC_T_BYTE MasterENI_xml_data_end[] asm("_binary_MasterENI_xml_end");
+#define STATIC_MASTERENI_XML_DATA MasterENI_xml_data
+#define STATIC_MASTERENI_XML_DATA_SIZE (size_t)((EC_T_VOID*)MasterENI_xml_data_size)
+#endif /* RTAI */
+
+#if (defined EC_VERSION_SYSBIOS) || (defined EC_VERSION_RIN32M3) ||\
+ (defined EC_VERSION_XILINX_STANDALONE) || (defined EC_VERSION_RZT1) || (defined EC_VERSION_ETKERNEL) ||\
+ (defined EC_VERSION_RZGNOOS)
+extern EC_T_BYTE MasterENI_xml_data[];
+extern EC_T_DWORD MasterENI_xml_data_size;
+
+#define STATIC_MASTERENI_XML_DATA MasterENI_xml_data
+#define STATIC_MASTERENI_XML_DATA_SIZE MasterENI_xml_data_size
+#endif
+
+#if (defined EC_VERSION_WINDOWS) || (defined VXWORKS) || ((defined UNDER_CE) && (_WIN32_WCE >= 0x600)) ||\
+ (defined UNDER_RTSS) || (defined STARTERWARE_NOOS) ||\
+ (defined EC_VERSION_SYSBIOS) || (defined EC_VERSION_RIN32M3) || (defined EC_VERSION_XILINX_STANDALONE) ||\
+ (defined EC_VERSION_RZT1) || (defined EC_VERSION_RZGNOOS) || ((defined LINUX) && (!defined RTAI) && (!defined XENOMAI))
+#define AUXCLOCK_SUPPORTED
+#endif
+
+/*-TYPEDEFS------------------------------------------------------------------*/
+typedef struct _EC_T_TIMING_DESC
+{
+ EC_T_VOID* pvTimingEvent; /* event handle */
+ EC_T_DWORD dwBusCycleTimeUsec; /* cycle time in usec */
+ EC_T_BOOL bShutdown; /* EC_TRUE if aux thread shall shut down */
+ EC_T_BOOL bIsRunning; /* EC_TRUE if the aux thread is running */
+#if (defined AUXCLOCK_SUPPORTED)
+ EC_T_BOOL bUseAuxClock; /* Either connect to IRQ or use sleep */
+ EC_T_VOID* pvAuxClkEvent; /* event handle */
+#endif
+ EC_T_DWORD dwCpuIndex; /* SMP systems: CPU index */
+#if ((defined UNDER_CE) && (_WIN32_WCE >= 0x600))
+ HANDLE hVirtualDrv; /* virtual IO driver handle */
+ VI_T_INTERRUPTDESC oIrqDesc; /* Irq descriptor for virtual IO driver */
+#endif
+} EC_T_TIMING_DESC;
+
+/*-GLOBAL VARIABLES-----------------------------------------------------------*/
+volatile EC_T_BOOL bRun = EC_TRUE;
+
+/*-LOCAL FUNCTIONS-----------------------------------------------------------*/
+#if (defined WIN32) && !(defined UNDER_CE)
+/********************************************************************************/
+/** \brief CTRL-C handler.
+*
+* \return N/A
+*/
+static BOOL WINAPI win32CtrlCHandler(DWORD dwCtrlType)
+{
+ UNREFERENCED_PARAMETER( dwCtrlType );
+
+ bRun = EC_FALSE;
+ return TRUE; // don't handle events
+}
+#endif /* WIN32 && !UNDER_CE */
+
+#if (defined VXWORKS)
+/********************************************************************************/
+/** \brief Change VxWorks task priority.
+*
+* \return N/A.
+*/
+EC_T_VOID vxTaskPrioChange( EC_T_CHAR* szTaskName )
+{
+#if (_WRS_VXWORKS_MAJOR < 7) || ! defined(_WRS_VXWORKS_MAJOR)
+int nTid = taskNameToId(szTaskName);
+ if (-1 != nTid)
+#else
+TASK_ID nTid = taskNameToId( szTaskName );
+ if (ERROR != taskIdVerify(nTid))
+#endif
+ {
+ int nPrio;
+
+ taskPriorityGet( nTid, &nPrio );
+ if( nPrio < 10 )
+ {
+ taskPrioritySet( nTid, nPrio + 10 );
+ }
+ }
+}
+/********************************************************************************/
+/** \brief VxWorks auxiliary clock ISR.
+*
+* \return N/A.
+*/
+EC_T_VOID vxAuxClkIsr( EC_T_INT nEvent )
+{
+ EC_T_VOID* pvEvent = (EC_T_VOID*)nEvent;
+ if( EC_NULL != pvEvent )
+ {
+ OsSetEvent(pvEvent);
+ }
+}
+#endif /* VXWORKS */
+
+#if (defined(RTOS_32) && !defined(_WINDLL))
+#if (defined ECWIN_RTOS32)
+static RTFileSystem Console = { RT_FS_CONSOLE, 0, 0, &RTConsoleFileSystem };
+static RTFileSystem LPTFiles = { RT_FS_LPT_DEVICE, 0, 0, &RTLPTFileSystem };
+static RTFileSystem RAMFiles = { RT_FS_FILE, 1 << ('D' - 'A'), 0, &RTRAMFileSystem };
+static RTFileSystem RtosLibFiles = { RT_FS_FILE | RT_FS_IS_DEFAULT, 1 << ('C' - 'A'), 0, &RTRtosLibFileSystem, 0, 0 };
+RTFileSystem * RTFileSystemList[] =
+{
+ &Console,
+ &LPTFiles,
+ &RAMFiles,
+ &RtosLibFiles,
+ NULL
+};
+#endif /* ECWIN_RTOS32 */
+extern "C" int __rttMaxPCIBusses;
+extern "C" {
+ RTK32Config RTKConfig = {
+ sizeof(RTK32Config), // StructureSize
+#if MP
+ DF_IDLE_HALT | // DriverFlags (MP kernel)
+#endif
+ 0, // DriverFlags
+ 0, // UserDriverFlags
+ RF_PREEMPTIVE | // preemptive
+ RF_AUTOINIT | RF_NAMED_WIN32CS,// Flags
+ 16*1024, // DefaultTaskStackSize
+#if MP
+ 1024, // DefaultIntStackSize
+#else
+ 512, // DefaultIntStackSize
+#endif
+ 5, // MainPriority
+ 0, // DefaultPriority
+ 0, // HookedInterrupts (none)
+ 256, // TaskStackOverhead
+ 0 // TimeSlice (0 == off)
+ } ;
+#ifdef _MSC_VER
+extern "C" __declspec(dllexport) void Init(void)
+#else
+extern "C" void __export Init(void)
+#endif
+{
+ __rttMaxPCIBusses = 255;
+ RTSetFlags(RT_MM_VIRTUAL | RT_CLOSE_FIND_HANDLES, 1);
+#ifdef ECWIN_RTOS32
+ RTVmfInit();
+ RTVmfExtendHeap();
+#else
+ RTCMOSExtendHeap();
+#endif
+}
+}
+#endif /* (RTOS_32 && !_WINDLL) */
+
+#if (defined LINUX) && !(defined RTAI)
+/********************************************************************************/
+/** \brief signal handler.
+*
+* \return N/A
+*/
+static void SignalHandler( int nSignal )
+{
+ bRun = EC_FALSE;
+}
+#endif
+
+#if (defined LINUX) && !(defined RTAI) && !(defined XENOMAI)
+/********************************************************************************/
+/** Enable real-time environment
+*
+* Return: EC_E_NOERROR in case of success, EC_E_ERROR in case of failure.
+*/
+EC_T_DWORD EnableRealtimeEnvironment( EC_T_VOID )
+{
+ struct utsname SystemName;
+ int nMaj, nMin, nSub;
+ struct timespec ts;
+ int nRetval;
+ EC_T_DWORD dwResult = EC_E_ERROR;
+ EC_T_BOOL bHighResTimerAvail;
+ struct sched_param schedParam;
+
+ /* master only tested on >= 2.6 kernel */
+ nRetval = uname( &SystemName );
+ if (nRetval != 0)
+ {
+ OsPrintf( "ERROR calling uname(), required Linux kernel >= 2.6\n" );
+ dwResult = EC_E_ERROR;
+ goto Exit;
+ }
+ sscanf( SystemName.release, "%d.%d.%d", &nMaj, &nMin, &nSub );
+ if (!(((nMaj == 2) && (nMin == 6)) || (nMaj >= 3)))
+ {
+ OsPrintf( "ERROR - detected kernel = %d.%d.%d, required Linux kernel >= 2.6\n", nMaj, nMin, nSub );
+ dwResult = EC_E_ERROR;
+ goto Exit;
+ }
+
+ /* request realtime scheduling for the current process
+ * This value is overwritten for each individual task
+ */
+ schedParam.sched_priority = MAIN_THREAD_PRIO; /* 1 lowest priority, 99 highest priority */
+ nRetval = sched_setscheduler( 0, SCHED_FIFO, &schedParam );
+ if (nRetval == -1)
+ {
+ OsPrintf( "ERROR - cannot change scheduling policy!\n"
+ "root privilege is required or realtime group has to be joined!\n" );
+ goto Exit;
+ }
+
+ /* disable paging */
+ nRetval = mlockall( MCL_CURRENT | MCL_FUTURE );
+ if (nRetval == -1)
+ {
+ OsPrintf( "ERROR - cannot disable paging!\n" );
+ dwResult = EC_E_ERROR;
+ goto Exit;
+ }
+
+ /* check if high resolution timers are available */
+ if (clock_getres(CLOCK_MONOTONIC, &ts))
+ {
+ bHighResTimerAvail = EC_FALSE;
+ }
+ else
+ {
+ bHighResTimerAvail = !(ts.tv_sec != 0 || ts.tv_nsec != 1);
+ }
+ if( !bHighResTimerAvail )
+ {
+ OsPrintf( "WARNING: High resolution timers not available\n" );
+ }
+
+ /* set type of OsSleep implementation (eSLEEP_USLEEP, eSLEEP_NANOSLEEP or eSLEEP_CLOCK_NANOSLEEP) */
+ OsSleepSetType( eSLEEP_CLOCK_NANOSLEEP );
+
+ dwResult = EC_E_NOERROR;
+Exit:
+ return dwResult;
+}
+#endif /* LINUX && !RTAI && !XENOMAI */
+
+#if (defined XENOMAI)
+static const char *reason_str[] = {
+ [SIGDEBUG_UNDEFINED] = "undefined",
+ [SIGDEBUG_MIGRATE_SIGNAL] = "received signal",
+ [SIGDEBUG_MIGRATE_SYSCALL] = "invoked syscall",
+ [SIGDEBUG_MIGRATE_FAULT] = "triggered fault",
+ [SIGDEBUG_MIGRATE_PRIOINV] = "affected by priority inversion",
+ [SIGDEBUG_NOMLOCK] = "missing mlockall",
+ [SIGDEBUG_WATCHDOG] = "runaway thread",
+};
+
+void warn_upon_switch(int sig, siginfo_t *si, void *context)
+{
+ unsigned int reason = si->si_value.sival_int;
+ void *bt[32];
+ int nentries;
+
+ printf("\nSIGDEBUG received, reason %d: %s\n", reason,
+ reason <= SIGDEBUG_WATCHDOG ? reason_str[reason] : "<unknown>");
+ /* Dump a backtrace of the frame which caused the switch to
+ secondary mode: */
+ nentries = backtrace(bt,sizeof(bt) / sizeof(bt[0]));
+ backtrace_symbols_fd(bt,nentries,fileno(stdout));
+}
+
+
+/********************************************************************************/
+/** Enable real-time environment
+*
+* Return: EC_E_NOERROR in case of success, EC_E_ERROR in case of failure.
+*/
+EC_T_DWORD EnableRealtimeEnvironment( EC_T_VOID )
+{
+ int nRetval = 0;
+ EC_T_DWORD dwRetVal = EC_E_ERROR;
+ struct sigaction sa;
+
+ /* Register callback for catching switches to Xenomai secondary mode */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = warn_upon_switch;
+ sa.sa_flags = SA_SIGINFO;
+ sigaction(SIGDEBUG, &sa, NULL);
+
+ /* disable paging */
+ nRetval = mlockall( MCL_CURRENT | MCL_FUTURE );
+ if (-1 == nRetval)
+ {
+ OsDbgMsg( "ERROR - cannot disable paging!\n" );
+ dwRetVal = EC_E_ERROR;
+ goto Exit;
+ }
+
+ /* this initialization is needed for using rt_printf functions */
+ /* rt_print_auto_init(1); */
+
+ /* Turns the current Linux task into a native Xenomai task.
+ *
+ * Using shadow with NULL pointer as RT_TASK is only available in
+ * recent Xenomai implementations!
+ */
+ nRetval = rt_task_shadow(NULL, "tEcMasterDemo", MAIN_THREAD_PRIO, 0);
+ if (0 != nRetval)
+ {
+ printf("ERROR - cannot make the current thread a realtime task (%d)\n", nRetval);
+ goto Exit;
+ }
+
+ /* Disable PRIMARY to SECONDARY MODE switch warning */
+ nRetval = rt_task_set_mode(T_WARNSW, 0, NULL);
+ if (nRetval != 0)
+ {
+ OsDbgMsg("OsCreateThread: rt_task_set_mode returned error %d\n", nRetval);
+ OsDbgAssert(EC_FALSE);
+ }
+
+ dwRetVal = EC_E_NOERROR;
+Exit:
+ return dwRetVal;
+}
+#endif /* XENOMAI */
+
+#if (defined UNDER_RTSS)
+VOID RTFCNDCL RtxAuxClkIsr(PVOID pvEvent)
+{
+ if( EC_NULL != pvEvent )
+ {
+ OsSetEvent(pvEvent);
+ }
+}
+#endif
+
+#if (defined ECWIN_RTOS32)
+/*******************************************************************************
+*
+* RdDbgPortChar - Read character from Debug PORT
+*
+* Return: TRUE if character was available, FALSE if not.
+*/
+BOOL RdDbgPortChar( UINT8* pbyData )
+{
+UINT32 dwNumRead;
+
+ vmfVioRead( 0, FALSE, pbyData, 1, &dwNumRead);
+ return (dwNumRead == 1);
+}
+
+extern volatile EC_T_BOOL bRun; /* global helper variable to shutdown the application */
+/*-----------------------------------*/
+#define CTRL_C 3
+#define ESC 27
+void tTerminationReq(void)
+{
+UINT8 byData;
+
+ /* flush input first */
+ while( RdDbgPortChar(&byData) )
+ {
+ Sleep(1);
+ }
+ for(;;)
+ {
+ Sleep(100);
+ if( RdDbgPortChar(&byData) )
+ {
+ if( (byData == CTRL_C) || (byData == ESC) )
+ {
+ bRun = 0;
+ break;
+ }
+ }
+ }
+}
+#endif /* ECWIN_RTOS32 */
+
+#if (defined ECWIN) && !(defined EXCLUDE_ECWIN_SHM)
+/*-----------------------------------*/
+BOOL OpenRtosLibShm(CHAR* szShmName, UINT8** ppbyShm, UINT32* pdwShmSize)
+{
+BOOL bRetVal = FALSE;
+UINT32 dwRes = RTE_SUCCESS;
+UINT32 dwShmId = 0;
+UINT32 dwTotalSize = 0;
+UINT8* pbyShm = EC_NULL;
+UINT32 dwGrantedSize = 0;
+
+ dwRes = RtosGetIdByNameA(szShmName, RTOS_ID_SHM, &dwShmId);
+ if (RTE_SUCCESS != dwRes)
+ {
+ goto Exit;
+ }
+ dwRes = RtosShmTotalSizeGet(dwShmId, &dwTotalSize);
+ if (RTE_SUCCESS != dwRes)
+ {
+ goto Exit;
+ }
+ dwRes = RtosShmAddrGet(dwShmId, dwTotalSize, &dwGrantedSize, (VOID**)&pbyShm);
+ if (RTE_SUCCESS != dwRes)
+ {
+ goto Exit;
+ }
+ if (dwTotalSize != dwGrantedSize)
+ {
+ goto Exit;
+ }
+ /* no errors */
+ *pdwShmSize = dwTotalSize;
+ *ppbyShm = pbyShm;
+ bRetVal = TRUE;
+
+Exit:
+ return bRetVal;
+}
+#endif /* ECWIN && !EXCLUDE_ECWIN_SHM */
+
+#if (defined EC_VERSION_RTEMS)
+/********************************************************************************/
+/** Timer ISR to trigger the job task
+*
+* Return: N/A
+*/
+rtems_timer_service_routine rtemsTimerIsr(rtems_id timerId, EC_T_VOID* pvEvent)
+{
+ if(EC_NULL != pvEvent)
+ {
+ OsSetEvent(pvEvent);
+ }
+ rtems_timer_reset(timerId);
+}
+/********************************************************************************/
+/** Mount Filesystems
+ * required to read ENI-File
+ * Maybe extend/change pDevname and fs_table to your needs
+ *
+ * Return: N/A
+*/
+EC_T_BOOL rtemsMountFilesystems()
+{
+ rtems_status_code status = RTEMS_NOT_DEFINED;
+ EC_T_BOOL bRes = EC_TRUE;
+ EC_T_INT rv;
+
+ const char* pDevname[] =
+ {
+ "/dev/hda",
+ "/dev/hdb"
+ };
+ fstab_t fsTable[] =
+ {
+ {"/dev/hda1", "/mnt/hda1", "dosfs", RTEMS_FILESYSTEM_READ_WRITE,
+ FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED, 0 },
+ {"/dev/hdb1", "/mnt/hdb1", "dosfs", RTEMS_FILESYSTEM_READ_WRITE,
+ FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED, 0 }
+ };
+ const EC_T_INT nNumDevs = 2;
+ /* Register partitions as logical disks */
+ for(EC_T_INT i = 0; i < nNumDevs; i++)
+ {
+ status = rtems_bdpart_register_from_disk(pDevname[i]);
+ if(status != RTEMS_SUCCESSFUL && status != RTEMS_INVALID_NUMBER)
+ {
+ OsDbgMsg("ATEMDemoMain: Failed to register %s\n", pDevname[i]);
+ OsDbgMsg("RTEMS returned: %s\n", rtems_status_text(status));
+ continue;
+ }
+ }
+ /* Mounts the file systems listed in the file system mount table */
+ rv = rtems_fsmount(fsTable, sizeof(fsTable) / sizeof(fsTable[0]), NULL);
+ if (rv != 0)
+ {
+ OsDbgMsg("ATEMDemoMain: cannot mount file system\n");
+ bRes = EC_FALSE;
+ }
+ return bRes;
+}
+
+/********************************************************************************/
+/** Sync Block Device Buffers to write data to the disk media
+*
+* Return: N/A
+*/
+void rtemsSyncBDBuffers(){
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ dev_t dev = (dev_t) -1;
+ rtems_disk_device *dd = NULL;
+
+ while(sc == RTEMS_SUCCESSFUL && (dd = rtems_disk_next(dev)) != NULL)
+ {
+ /* Synchronize all modified buffers for device dd */
+ sc = rtems_bdbuf_syncdev(dd);
+ if( sc != RTEMS_SUCCESSFUL)
+ {
+ OsDbgMsg("Device: %s sync buffers failed\n", dd->name);
+ }
+ /* get next dev for rtems_disk_next iterator */
+ dev = rtems_disk_get_device_identifier(dd);
+ sc = rtems_disk_release(dd);
+ }
+ /* Sleep a while to be ensure that the buffers are synced */
+ OsSleep(5000);
+}
+#endif /* EC_VERSION_RTEMS */
+
+/********************************************************************************/
+/** Show syntax
+*
+* Return: N/A
+*/
+static EC_T_VOID ShowSyntax(EC_T_VOID)
+{
+ OsDbgMsg("Syntax:\n");
+ OsDbgMsg("EcMasterDemo [-f ENI-FileName] [-t time] [-b time] [-a affinity] [-v lvl] [-perf] [-log Prefix]");
+#if (defined AUXCLOCK_SUPPORTED)
+ OsDbgMsg(" [-auxclk period]");
+#endif
+#if (defined ATEMRAS_SERVER)
+ OsDbgMsg(" [-sp [port]]");
+#endif
+ ShowLinkLayerSyntax1();
+ OsDbgMsg(" -f Use given ENI file\n");
+ OsDbgMsg(" FileName file name .xml\n");
+ OsDbgMsg(" -t Demo duration\n");
+ OsDbgMsg(" time Time in msec, 0 = forever (default = 120000)\n");
+ OsDbgMsg(" -b Bus cycle time\n");
+ OsDbgMsg(" cycle time Cycle time in usec\n");
+ OsDbgMsg(" -a CPU affinity\n");
+ OsDbgMsg(" affinity 0 = first CPU, 1 = second, ...\n");
+ OsDbgMsg(" -v Set verbosity level\n");
+ OsDbgMsg(" lvl Level: 0=off, 1(default) ...n=more messages\n");
+ OsDbgMsg(" -perf Enable job measurement\n");
+ OsDbgMsg(" -log Use given file name prefix for log files\n");
+ OsDbgMsg(" Prefix prefix\n");
+#if (defined AUXCLOCK_SUPPORTED)
+ OsDbgMsg(" -auxclk use auxiliary clock\n");
+ OsDbgMsg(" period clock period in usec\n" );
+#endif
+#if (defined ATEMRAS_SERVER)
+ OsDbgMsg(" -sp Server port binding\n");
+ OsDbgMsg(" port port (default = %d)\n", ATEMRAS_DEFAULT_PORT);
+#endif
+ ShowLinkLayerSyntax2();
+
+ return;
+}
+
+#if !(defined RTAI) && !(defined XENOMAI)
+/********************************************************************************/
+/* \brief Set event according to periodical sleep or aux clock
+ * Cyclically sets an event for thread synchronization purposes.
+ * Either use OsSleep() or use the aux clock by means of:
+ * - Enable AUX clock if selected.
+ * - Wait for IRQ, aknowledge IRQ, SetEvent in loop until shutdown
+ * - Disable AUX clock
+ * Return: N/A
+ */
+static EC_T_VOID tEcTimingTask( EC_T_VOID* pvThreadParamDesc )
+{
+EC_T_TIMING_DESC* pTimingDesc = (EC_T_TIMING_DESC*)pvThreadParamDesc;
+EC_T_CPUSET CpuSet;
+#if (defined QNX6)
+ struct _clockperiod oClockPeriod = {0};
+#elif (defined __INTIME__)
+ RTHANDLE hTimingAlarm;
+#endif
+
+ EC_CPUSET_ZERO( CpuSet );
+ EC_CPUSET_SET( CpuSet, pTimingDesc->dwCpuIndex );
+ OsSetThreadAffinity( EC_NULL, CpuSet );
+
+#if ((defined UNDER_CE) && (_WIN32_WCE >= 0x600))
+ /* enable auxilary clock */
+ if (pTimingDesc->bUseAuxClock)
+ {
+ DWORD dwAuxClkFreq = 1000000 / pTimingDesc->dwBusCycleTimeUsec;
+
+ if (!KernelIoControl((DWORD)IOCTL_AUXCLK_ENABLE, &dwAuxClkFreq, sizeof(DWORD), NULL, 0, NULL))
+ {
+ OsDbgMsg("Error calling KernelIoControl(IOCTL_AUXCLK_ENABLE) (0x%08X)!\n", GetLastError());
+ goto Exit;
+ }
+ }
+#elif (defined QNX6)
+ /* Set the clock period to bus cycle time */
+ oClockPeriod.nsec = pTimingDesc->dwBusCycleTimeUsec * 1000;
+ if(ClockPeriod(CLOCK_REALTIME, &oClockPeriod, EC_NULL, 0) == -1)
+ {
+ OsPrintf("tEcTimingTask:: Cannot set the clock period! Error %i", errno);
+ }
+#elif (defined __INTIME__)
+ hTimingAlarm = CreateRtAlarm(KN_REPEATER, pTimingDesc->dwBusCycleTimeUsec);
+#endif
+
+ /* timing task started */
+ pTimingDesc->bIsRunning = EC_TRUE;
+
+ /* periodically generate events as long as the application runs */
+ while (!pTimingDesc->bShutdown)
+ {
+ /* wait for the next cycle */
+#if ((defined UNDER_CE) && (_WIN32_WCE >= 0x600))
+
+ if (pTimingDesc->bUseAuxClock)
+ {
+ /* wait for auxclk event */
+ OsWaitForEvent(pTimingDesc->pvAuxClkEvent, EC_WAITINFINITE);
+
+ if (pTimingDesc->bShutdown)
+ {
+ /* disable auxilary clock */
+ if (!KernelIoControl((DWORD)IOCTL_AUXCLK_DISABLE, NULL, 0, NULL, 0, NULL))
+ {
+ OsDbgMsg("Error calling KernelIoControl(IOCTL_AUXCLK_DISABLE) (0x%08X)!\n", GetLastError());
+ }
+ }
+ /* Acknowledge the IRQ */
+ if (pTimingDesc->hVirtualDrv != NULL)
+ {
+ DeviceIoControl(pTimingDesc->hVirtualDrv, (DWORD)IOCTL_VIRTDRV_INTERRUPT_DONE, &(pTimingDesc->oIrqDesc), sizeof(VI_T_INTERRUPTDESC), NULL, 0, NULL, NULL );
+ }
+ }
+ else
+ {
+ /* wait for next cycle (no cycle below 1ms) */
+ OsSleep(EC_MAX(pTimingDesc->dwBusCycleTimeUsec / 1000, 1));
+ }
+ /* UNDER_CE, _WIN32_WCE < 0x600 */
+#elif (defined RTOS_32)
+ {
+ /* wait for next cycle (sleep of zero allow cycle below 1ms) */
+ OsSleep(pTimingDesc->dwBusCycleTimeUsec / 1000);
+ }
+ /* RTOS_32 */
+#elif (defined QNX6)
+ {
+ /* wait for next cycle */
+ OsSleep(1);
+ }
+ /* QNX6 */
+#elif (defined __INTIME__)
+ {
+ WaitForRtAlarm(hTimingAlarm, 2*pTimingDesc->dwBusCycleTimeUsec);
+ }
+#else
+ {
+ /* wait for next cycle (no cycle below 1ms) */
+ OsSleep(EC_MAX(pTimingDesc->dwBusCycleTimeUsec / 1000, 1));
+ }
+#endif
+ /* trigger jobtask */
+ OsSetEvent( pTimingDesc->pvTimingEvent );
+ }
+
+#if ((defined UNDER_CE) && (_WIN32_WCE >= 0x600))
+Exit:
+#endif
+#if (defined __INTIME__)
+ if (NULL != hTimingAlarm)
+ {
+ DeleteRtAlarm(hTimingAlarm);
+ }
+#endif
+ pTimingDesc->bIsRunning = EC_FALSE;
+#if (defined EC_VERSION_RTEMS)
+ rtems_task_delete(RTEMS_SELF);
+#endif
+ return;
+}
+#endif /* !RTAI && !XENOMAI */
+
+/********************************************************************************/
+/** \brief Demo Application entry point.
+*
+* \return Value 0 is returned.
+*/
+#if (defined VXWORKS)
+extern "C" int atemDemo(char* lpCmdLine)
+#elif (defined __TKERNEL)
+EXPORT ER main( INT nArgc, char** ppArgv )
+#elif (defined RTOS_32)
+# if (defined _WINDLL)
+# ifdef _MSC_VER
+extern "C" __declspec(dllexport) int main(void)
+# else /* _MSC_VER */
+extern "C" int __export main(void)
+# endif /* else _MSC_VER */
+# else /* _WINDLL */
+ int main(void)
+# endif /* else _WINDLL */
+#elif (defined __RCX__)
+TLR_RESULT atemDemo(TLR_VOID FAR* pvInit)
+#elif (defined STARTERWARE_NOOS)
+extern "C" int EcMasterDemo(int nArgc, char* ppArgv[])
+#elif (defined RTAI)
+extern "C" void EcMasterDemoMain(long int t)
+#elif (defined UNDER_CE)
+int _tmain(int nArgc, _TCHAR* ppArgv[])
+#elif (defined EC_VERSION_SYSBIOS) || (defined EC_VERSION_RIN32M3) || (defined EC_VERSION_XILINX_STANDALONE) ||\
+ (defined EC_VERSION_ETKERNEL) || (defined EC_VERSION_RZT1) || (defined EC_VERSION_RZGNOOS)
+extern "C" int EcMasterDemo(void)
+#elif (defined EC_VERSION_UCOS)
+int ucosiiiMain(int nArgc, char** ppArgv)
+#elif (defined EC_VERSION_RTEMS)
+rtems_task Main(rtems_task_argument rtemsArg)
+#else
+/* QNX6, LINUX, __INTEGRITY, ... */
+int main(int nArgc, char* ppArgv[])
+#endif
+{
+ int nRetVal = APP_ERROR;
+ EC_T_DWORD dwRes = EC_E_ERROR;
+ EC_T_BOOL bLogInitialized = EC_FALSE;
+ EC_T_CHAR szCommandLine[COMMAND_LINE_BUFFER_LENGTH];
+ EC_T_CHAR szFullCommandLine[COMMAND_LINE_BUFFER_LENGTH];
+ EC_T_BOOL bGetNextWord = EC_TRUE;
+ EC_T_CHAR* ptcWord = EC_NULL;
+ EC_T_CHAR tcStorage = '\0';
+
+ EC_T_CHAR szLogFileprefix[256] = {'\0'};
+ EC_T_CNF_TYPE eCnfType = eCnfType_Unknown;
+ EC_T_PBYTE pbyCnfData = 0;
+ EC_T_DWORD dwCnfDataLen = 0;
+ EC_T_CHAR szENIFilename[256] = {'\0'};
+ EC_T_DWORD dwDuration = 120000;
+ EC_T_DWORD dwNumLinkLayer = 0;
+ EC_T_LINK_PARMS* apLinkParms[MAX_LINKLAYER];
+#ifdef ATEMRAS_SERVER
+ EC_T_WORD wServerPort = 0xFFFF;
+#endif
+ CAtEmLogging oLogging;
+ EC_T_DWORD dwCpuIndex = 0;
+ EC_T_CPUSET CpuSet;
+ EC_T_BOOL bEnaPerfJobs = EC_FALSE; /* enable job measurements */
+ EC_T_TIMING_DESC TimingDesc;
+#if !(defined XENOMAI)
+ EC_T_BOOL bStartTimingTask = EC_FALSE;
+#endif
+ EC_T_INT nVerbose = 1;
+#if (defined UNDER_CE) && (_WIN32_WCE >= 0x600)
+ BOOL bRes = FALSE;
+ DWORD dwAuxClkSysIntr = 0;
+ DWORD dwWinRes = EC_E_ERROR;
+#endif
+#if (defined UNDER_RTSS)
+ HANDLE hTimer = NULL;
+ LARGE_INTEGER liTimer;
+#endif
+#if (defined EC_VERSION_RTEMS)
+ rtems_id timerId;
+ rtems_status_code status;
+#endif /* EC_VERSION_RTEMS */
+ OsMemset(apLinkParms, 0, sizeof(apLinkParms));
+ OsMemset(&TimingDesc, 0, sizeof(TimingDesc));
+
+ szCommandLine[0] = '\0';
+
+ /* OS specific initialization */
+#if (defined WIN32) && !(defined UNDER_CE)
+ SetConsoleCtrlHandler( (PHANDLER_ROUTINE)win32CtrlCHandler, TRUE );
+#endif
+
+#if (defined RTOS_32)
+#ifdef ECWIN_RTOS32
+ RTKernelInit(0);
+#else
+ RTKernelInit(4);
+ RTCMOSSetSystemTime();
+#endif
+ RTKPreemptionsON();
+#if (defined ATEMRAS_SERVER) && (defined EC_SOCKET_IP_SUPPORTED) && (defined INCLUDE_RTIP)
+ NetInitialize();
+#endif
+#endif /* RTOS_32 */
+#if (defined ECWIN_RTOS32)
+ {
+ void* pvReg = NULL;
+
+ /* protect memory area at address 0 (detect NULL pointer access) */
+ pvReg = NULL;
+ RTReserveVirtualAddress(&pvReg, 0x1000, RT_MAP_NO_RELOCATE);
+
+ /* start thread waiting for termination request */
+ RTKRTLCreateThread( (RTKThreadFunction)tTerminationReq, 64, 0x1000, TF_NO_MATH_CONTEXT, NULL, "tTerminationReq" );
+
+ printf( "you can stop the demo by typing CTRL-C or ESCAPE in the debug console\n");
+ }
+#endif /* ECWIN_RTOS32 */
+#if (defined ECWIN)
+ /* must be call before any RtosLib API call */
+ RtosLibInit();
+#endif /* ECWIN */
+
+#if (defined VXWORKS)
+ /* change VxWorks standard task priorities to optimize EtherCAT performance */
+#ifndef VXWORKS_NORMAL_PRIO
+ vxTaskPrioChange( "tJobTask" );
+ vxTaskPrioChange( "tLogTask" );
+ vxTaskPrioChange( "tNbioLog" );
+ vxTaskPrioChange( "tShell" );
+ vxTaskPrioChange( "tShell0" );
+ vxTaskPrioChange( "tShellRem1" );
+ vxTaskPrioChange( "tShellRem2" );
+ vxTaskPrioChange( "tWdbTask" );
+ vxTaskPrioChange( "tTelnetd" );
+#endif
+#if ((defined _WRS_VXWORKS_MAJOR) && (defined _WRS_VXWORKS_MINOR) && ( (_WRS_VXWORKS_MAJOR >= 7) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 5)) ))
+ taskPrioritySet( taskNameToId("tNet0"), RECV_THREAD_PRIO );
+#else
+ taskPrioritySet( taskNameToId("tNetTask"), RECV_THREAD_PRIO );
+#endif
+ /* redirect outputs to target shell console device */
+#if (_WRS_VXWORKS_MAJOR < 7) || ! defined(_WRS_VXWORKS_MAJOR)
+ int nTidTargetShell = taskNameToId("tShellRem1");
+ if (-1 != nTidTargetShell)
+#else
+ TASK_ID nTidTargetShell = taskNameToId("tShellRem1");
+ if (ERROR != taskIdVerify(nTidTargetShell))
+#endif
+ {
+ /* redirect all outputs at the target shell */
+ ioGlobalStdSet (STD_OUT, ioTaskStdGet(nTidTargetShell,STD_OUT));
+ ioGlobalStdSet (STD_ERR, ioTaskStdGet(nTidTargetShell,STD_ERR));
+ }
+ /* sysclk always set to 1msec */
+ sysClkRateSet(1000);
+#endif /* VXWORKS */
+
+#if (defined LINUX) && !(defined RTAI)
+ dwRes = EnableRealtimeEnvironment();
+ if (EC_E_NOERROR != dwRes)
+ {
+ goto Exit;
+ }
+ {
+ sigset_t SigSet;
+ int nSigNum = SIGALRM;
+ sigemptyset(&SigSet);
+ sigaddset(&SigSet, nSigNum);
+ sigprocmask(SIG_BLOCK, &SigSet, NULL);
+ signal(SIGINT, SignalHandler);
+ signal(SIGTERM, SignalHandler);
+ }
+#endif /* LINUX && !RTAI */
+
+#if (defined __INTEGRITY)
+ WaitForFileSystemInitialization();
+#endif
+
+#if (defined __RCX__)
+ ATEMDEMO_STARTUPPARAMETER_T* pStartup = ((ATEMDEMO_STARTUPPARAMETER_T*)pvInit);
+
+ TCHAR* lpCmdLine = (TCHAR*)(pStartup->szParamList);
+ lpCmdLine = (lpCmdLine==EC_NULL)?(TCHAR*)" ":lpCmdLine;
+ tcStorage = *lpCmdLine;
+#endif
+
+#if (defined EC_VERSION_GO32)
+ if (!io_Init())
+ {
+ OsDbgMsg("Fail to initialize Vortex86 I/O library\n");
+ nRetVal = APP_ERROR;
+ goto Exit;
+ }
+ if (!irq_Init())
+ {
+ OsDbgMsg("Fail to initialize Vortex86 IRQ library\n");
+ io_Close(); /* Deinit IOs */
+ nRetVal = APP_ERROR;
+ goto Exit;
+ }
+#endif
+
+#if !(defined UNDER_RTSS) && !(defined RTAI)
+ /* Seed the random-number generator with current time so that
+ * the numbers will be different every time we run.
+ */
+ srand((unsigned)OsQueryMsecCount());
+#endif
+ /* set running flag */
+ bRun = EC_TRUE;
+
+ /* add hook to log all EtherCAT messages. Without hook no messages will be generated! */
+ OsAddDbgMsgHook(CAtEmLogging::OsDbgMsgHookWrapper);
+
+ /* Initialize Timing Event descriptor */
+ TimingDesc.bShutdown = EC_FALSE;
+ TimingDesc.bIsRunning = EC_FALSE;
+#if (defined RTAI)
+ TimingDesc.dwBusCycleTimeUsec = G_dwBusCycleTimeUsec;
+#else
+ TimingDesc.dwBusCycleTimeUsec = CYCLE_TIME * 1000;
+#endif
+
+ /* prepare command line */
+#if (defined VXWORKS)
+ OsStrncpy(szCommandLine, lpCmdLine, sizeof(szCommandLine) - 1);
+#elif (defined RTOS_32)
+#if (defined ECWIN_RTOS32)
+ {
+ VMF_HANDLE hEcatKey;
+ VMF_CONFIG_ADDDATA AddData;
+ UINT32 dwLength = 0;
+
+ dwRes = vmfConfigRegKeyOpenA(VMF_CONFIGREG_HKEY_OS_CURRENT, "Ecat", &hEcatKey);
+ if( dwRes == RTE_SUCCESS )
+ {
+
+ dwLength = sizeof(szCommandLine);
+ vmfConfigRegValueQueryA(hEcatKey, "CommandLine", NULL, NULL, (UINT8*)&szCommandLine[0], &dwLength );
+ vmfConfigRegKeyClose(hEcatKey);
+ }
+ if ('\0' == szCommandLine[0])
+ {
+ /* for compatibility */
+ dwLength = sizeof(szCommandLine);
+ dwRes = vmfConfigQueryValue( "Ecat", "CommandLine", VMF_CONFIG_SZ_TYPE, (UINT8*)&szCommandLine[0], &dwLength, &AddData);
+ if( dwRes != RTE_SUCCESS )
+ {
+ printf( "Cannot read EtherCAT demo command line, (EcatShm.config)\n" );
+ printf( "Please, enter command line (e.g. atemDemo -v 2 -i8255x 1 1):\n" );
+ }
+ }
+ }
+#else
+ OsStrncpy(szCommandLine, GetCommandLine(), sizeof(szCommandLine) - 1);
+#endif /* !ECWIN_RTOS32 */
+#elif (defined RTAI)
+ OsStrncpy(szCommandLine, "-i8254x 1 1 -v 1 -t 15000 ", sizeof(szCommandLine) - 1);
+#elif (defined __TKERNEL) && (defined __arm__)
+ /*-fixed command line for T-Kernel on ARM */
+ OsStrncpy(szCommandLine, "-l9218i 1 -v 1 -t 0 -f eni.xml", sizeof(szCommandLine) - 1);
+#elif (defined EC_VERSION_SYSBIOS) || (defined EC_VERSION_RIN32M3) || (defined EC_VERSION_XILINX_STANDALONE) ||\
+ (defined EC_VERSION_ETKERNEL) || (defined EC_VERSION_RZT1) || (defined EC_VERSION_RZGNOOS)
+ OsStrncpy(szCommandLine, DEMO_PARAMETERS, sizeof(szCommandLine) - 1);
+#elif (defined EC_VERSION_RTEMS)
+ /* copy cmdline without the applications name(first token) */
+ OsStrncpy(szCommandLine, strchr(bsp_boot_cmdline,' '),sizeof(szCommandLine) - 1);
+#else
+ /* build szCommandLine from argument list */
+ {
+ EC_T_CHAR* pcStrCur = szCommandLine;
+ EC_T_INT nStrRemain = COMMAND_LINE_BUFFER_LENGTH;
+#if (defined UNDER_CE)
+ EC_T_CHAR szStrFormat[] = "%S"; /* convert UNICODE to multibyte */
+#else
+ EC_T_CHAR szStrFormat[] = "%s";
+#endif
+ /* build szCommandLine from argument list, skipping executable name */
+ for (nArgc--, ppArgv++; nArgc > 0; nArgc--, ppArgv++)
+ {
+ EC_T_BOOL bIsFileName = EC_FALSE;
+
+ /* insert next argument */
+ OsSnprintf(pcStrCur, nStrRemain - 1, szStrFormat, *ppArgv);
+
+ /* check for file name */
+ if (0 == OsStrcmp(pcStrCur, "-f"))
+ {
+ bIsFileName = EC_TRUE;
+ }
+ /* adjust string cursor */
+ nStrRemain -= (EC_T_INT)OsStrlen(pcStrCur);
+ pcStrCur = pcStrCur + OsStrlen(pcStrCur);
+
+ /* insert space */
+ OsStrncpy(pcStrCur, " ", nStrRemain - 1); nStrRemain--; pcStrCur++;
+
+ if (bIsFileName && (1 < nArgc))
+ {
+ /* move to next arg (ENI file name) */
+ nArgc--; ppArgv++;
+
+ /* insert quotation mark */
+ OsStrncpy(pcStrCur, "\"", nStrRemain - 1); nStrRemain--; pcStrCur++;
+
+ /* insert ENI file name */
+ OsSnprintf(pcStrCur, nStrRemain - 1, szStrFormat, *ppArgv); nStrRemain -= (EC_T_INT)OsStrlen(pcStrCur);
+ pcStrCur = pcStrCur + OsStrlen(pcStrCur);
+
+ /* insert quotation mark */
+ OsStrncpy(pcStrCur, "\" ", nStrRemain - 1); nStrRemain--; pcStrCur++;
+ }
+ }
+ }
+#endif
+ /* backup full command line */
+ OsStrncpy(szFullCommandLine, szCommandLine, sizeof(szFullCommandLine) - 1);
+
+ /* parse command line */
+ for (ptcWord = OsStrtok(szCommandLine, " "); ptcWord != EC_NULL;)
+ {
+ if( 0 == OsStricmp( ptcWord, "-f") )
+ {
+ EC_T_INT nPtcWordIndex = 3;
+
+ /* Search for the start of the config file name. The config file
+ name may start with quotation marks because of blanks in the filename */
+ while(ptcWord[nPtcWordIndex] != '\0')
+ {
+ if(ptcWord[nPtcWordIndex] == '\"' || ptcWord[nPtcWordIndex] != ' ')
+ {
+ break;
+ }
+ nPtcWordIndex++;
+ }
+
+ /* Depending of a config file name within quotation marks (or without
+ quotation marks) extract the filename */
+ if(ptcWord[nPtcWordIndex] == '\"')
+ {
+ /* Check if the strtok position is already correct */
+ if(nPtcWordIndex > 3)
+ {
+ /* More than 1 blank before -f. Correct strtok position. */
+ OsStrtok(EC_NULL,"\"");
+ }
+
+ /* Now extract the config file name */
+ ptcWord = OsStrtok(EC_NULL,"\"");
+ }
+ else
+ {
+ /* Extract the config file name if it was not set within quotation marks */
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage );
+ }
+
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ OsSnprintf(szENIFilename, sizeof(szENIFilename) - 1, "%s", ptcWord);
+ }
+ else if( 0 == OsStricmp( ptcWord, "-log") )
+ {
+ EC_T_INT nPtcWordIndex = 4;
+
+ /* Search for the start of the config file name. The config file
+ name may start with quotation marks because of blanks in the filename */
+ while(ptcWord[nPtcWordIndex] != '\0')
+ {
+ if(ptcWord[nPtcWordIndex] == '\"' || ptcWord[nPtcWordIndex] != ' ')
+ {
+ break;
+ }
+ nPtcWordIndex++;
+ }
+
+ /* Depending of a config file name within quotation marks (or without
+ quotation marks) extract the filename */
+ if(ptcWord[nPtcWordIndex] == '\"')
+ {
+ /* Check if the strtok position is already correct */
+ if(nPtcWordIndex > 3)
+ {
+ /* More than 1 blank before -f. Correct strtok position. */
+ OsStrtok(EC_NULL,"\"");
+ }
+
+ /* Now extract the config file name */
+ ptcWord = OsStrtok(EC_NULL,"\"");
+ }
+ else
+ {
+ /* Extract the config file name if it was not set within quotation marks */
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage );
+ }
+
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ OsSnprintf(szLogFileprefix, sizeof(szLogFileprefix) - 1, "%s", ptcWord);
+ }
+ else if (OsStricmp( ptcWord, "-t") == 0)
+ {
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage );
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ dwDuration = OsStrtol(ptcWord, EC_NULL, 0);
+ }
+ else if( OsStricmp( ptcWord, "-auxclk") == 0)
+ {
+#if (defined AUXCLOCK_SUPPORTED)
+ TimingDesc.bUseAuxClock = EC_TRUE;
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage);
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ TimingDesc.dwBusCycleTimeUsec = OsStrtol(ptcWord, EC_NULL, 0);
+ if( TimingDesc.dwBusCycleTimeUsec < 10 )
+ {
+ TimingDesc.dwBusCycleTimeUsec = 10;
+ }
+#else
+ OsDbgMsg( "Auxiliary clock not supported by this operating system!)\n" );
+ goto Exit;
+#endif
+ }
+ else if (OsStricmp( ptcWord, "-b") == 0)
+ {
+#if (defined AUXCLOCK_SUPPORTED)
+ if( EC_TRUE == TimingDesc.bUseAuxClock )
+ {
+ OsDbgMsg( "Using bus cycle time %d usec from auxclock parameter\n", TimingDesc.dwBusCycleTimeUsec );
+ }
+ else
+#endif
+ {
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage );
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ TimingDesc.dwBusCycleTimeUsec = OsStrtol(ptcWord, EC_NULL, 0);
+ }
+ }
+ else if (OsStricmp( ptcWord, "-a") == 0)
+ {
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage);
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ dwCpuIndex = OsStrtol(ptcWord, EC_NULL, 0);
+ }
+ else if (OsStricmp( ptcWord, "-v") == 0)
+ {
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage);
+ if (
+ (ptcWord == EC_NULL)
+ || (OsStrncmp( ptcWord, "-", 1) == 0)
+ )
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ nVerbose = OsStrtol(ptcWord, EC_NULL, 10);
+ }
+ else if (OsStricmp( ptcWord, "-perf") == 0)
+ {
+ bEnaPerfJobs = EC_TRUE;
+ }
+#if (defined ATEMRAS_SERVER)
+ else if( OsStricmp(ptcWord, "-sp") == 0 )
+ {
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage);
+ if ((ptcWord == NULL) || (OsStrncmp(ptcWord, "-", 1) == 0))
+ {
+ wServerPort = ATEMRAS_DEFAULT_PORT;
+
+ /* optional sub parameter not found, use the current word for the next parameter */
+ bGetNextWord = EC_FALSE;
+ }
+ else
+ {
+ wServerPort = (EC_T_WORD)OsStrtol(ptcWord, EC_NULL, 10);
+ }
+ }
+#endif
+ else
+ {
+ dwRes = CreateLinkParmsFromCmdLine(&ptcWord, (EC_T_CHAR**)&szCommandLine, &tcStorage, &bGetNextWord, &apLinkParms[dwNumLinkLayer]);
+ if (EC_E_NOERROR != dwRes)
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ if (dwNumLinkLayer > 1)
+ {
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+ else
+ {
+#ifdef LINUX
+ EC_CPUSET_ZERO(CpuSet);
+ EC_CPUSET_SET(CpuSet, dwCpuIndex);
+ apLinkParms[dwNumLinkLayer]->dwIstPriority = (CpuSet << 16) | RECV_THREAD_PRIO;
+#else
+ apLinkParms[dwNumLinkLayer]->dwIstPriority = RECV_THREAD_PRIO;
+#endif
+ dwNumLinkLayer++;
+ }
+ }
+ /* get next word */
+ if (bGetNextWord)
+ {
+ ptcWord = GetNextWord((EC_T_CHAR**)&szCommandLine, &tcStorage );
+ }
+ bGetNextWord = EC_TRUE;
+ }
+ /* initialize master logging */
+#if (defined ECWIN) && !(defined EXCLUDE_ECWIN_SHM)
+ /* if EXCLUDE_ECWIN_SHM is defined, log messages are redirected to file */
+ /* if not log messages are directed to shared memory for compatibility */
+#if (defined ECWIN_CE)
+ if ('\0' != szLogFileprefix[0])
+ {
+ bLogFileEnb = EC_FALSE;
+ }
+ else
+ {
+ /* legacy log handling */
+ }
+#else
+ bLogFileEnb = EC_FALSE;
+#endif
+#endif
+ oLogging.InitLogging(0, LOG_ROLLOVER, LOG_THREAD_PRIO, dwCpuIndex, szLogFileprefix, LOG_THREAD_STACKSIZE);
+ bLogInitialized = EC_TRUE;
+#if !(defined XENOMAI)
+ oLogging.SetLogThreadAffinity(dwCpuIndex);
+#endif /* !XENOMAI */
+ OsAddDbgMsgHook(CAtEmLogging::OsDbgMsgHookWrapper);
+ LogMsg("Full command line: %s\n", szFullCommandLine);
+
+#if (defined ECWIN) && !(defined EXCLUDE_ECWIN_SHM)
+ if ('\0' != szLogFileprefix[0])
+ {
+ BYTE* pbyShm = NULL;
+ UINT32 dwShmSize = 0;
+ CHAR szShmName[256];
+
+ /* get a pointer to the master log */
+ OsSnprintf(szShmName, sizeof(szShmName) - 1, "%s.log", szLogFileprefix);
+ if (OpenRtosLibShm(szShmName, &pbyShm, &dwShmSize))
+ {
+ oLogging.SetLogMsgBuf(pbyShm, dwShmSize);
+ }
+ else
+ {
+#if (defined ECWIN_CE)
+ LogMsg("Cannot open shared memory '%s', try to use file system\n", szShmName);
+#else
+ LogError("Error cannot open shared memory '%s'\n", szShmName);
+ return 0;
+#endif
+ }
+ /* get a pointer to the DCM log */
+ OsSnprintf(szShmName, sizeof(szShmName) - 1, "%s_dcm.log", szLogFileprefix);
+ if (OpenRtosLibShm(szShmName, &pbyShm, &dwShmSize))
+ {
+ oLogging.SetLogDcmBuf(pbyShm, dwShmSize);
+ }
+ else
+ {
+#if (defined ECWIN_CE)
+ LogMsg("Cannot open shared memory '%s', try to use file system\n", szShmName);
+#else
+ LogError("Error cannot open shared memory '%s'\n", szShmName);
+ return 0;
+#endif
+ }
+ }
+#endif /* ECWIN && !EXCLUDE_ECWIN_SHM */
+
+ /* determine master configuration type */
+#if (defined ECWIN) && !(defined EXCLUDE_ECWIN_SHM)
+#if (defined ECWIN_RTOS32)
+ if ('\0' == szENIFilename[0])
+ {
+ /* for compatibility */
+ OsSnprintf(szENIFilename, sizeof(szENIFilename) - 1, "MasterENI");
+ }
+#endif
+ if (('\0' == szENIFilename[0]) || ('0' == szENIFilename[0]))
+ {
+ /* filename is empty or "0" */
+ eCnfType = eCnfType_GenPreopENI;
+ }
+ else
+ {
+ /* get a pointer to the master log */
+ if (OpenRtosLibShm(szENIFilename, &pbyCnfData, &dwCnfDataLen))
+ {
+ eCnfType = eCnfType_Data;
+ }
+ else
+ {
+#if (defined ECWIN_CE)
+ eCnfType = eCnfType_Filename;
+ pbyCnfData = (EC_T_BYTE*)&szENIFilename[0];
+ dwCnfDataLen = 256;
+
+ LogMsg("Cannot open shared memory '%s', try to use file system\n", szENIFilename);
+#else
+ if (OsStrncmp(szENIFilename, "MasterENI", 9) == 0)
+ {
+ /* for compatibility */
+ eCnfType = eCnfType_GenPreopENI;
+
+ LogMsg("Cannot open shared memory '%s', use auto generated ENI until PreOP\n", szENIFilename);
+ }
+ else
+ {
+ LogMsg("Cannot open shared memory '%s'\n", szENIFilename);
+
+ return 0;
+ }
+#endif
+ }
+ }
+#elif (defined __RCX__)
+ eCnfType = eCnfType_Data;
+ pbyCnfData = pStartup->pBecFile;
+ dwCnfDataLen = pStartup->dwBecFileLen;
+#else /* default */
+ if ('\0' != szENIFilename[0])
+ {
+ eCnfType = eCnfType_Filename;
+ pbyCnfData = (EC_T_BYTE*)&szENIFilename[0];
+ dwCnfDataLen = 256;
+ }
+ else
+ {
+#if (defined STATIC_MASTERENI_XML_DATA)
+ eCnfType = eCnfType_Data;
+ pbyCnfData = STATIC_MASTERENI_XML_DATA;
+ dwCnfDataLen = STATIC_MASTERENI_XML_DATA_SIZE;
+#else
+ eCnfType = eCnfType_GenPreopENI;
+#endif
+ }
+#endif
+ if (0 == dwNumLinkLayer)
+ {
+ OsDbgMsg("Syntax error: missing link layer command line parameter\n");
+ nRetVal = SYNTAX_ERROR;
+ goto Exit;
+ }
+#if !(defined RTAI)
+ /* for multi core cpus: select cpu number for this thread */
+ EC_CPUSET_ZERO( CpuSet );
+ EC_CPUSET_SET( CpuSet, dwCpuIndex );
+ if( ! OsSetThreadAffinity(EC_NULL, CpuSet) )
+ {
+ OsDbgMsg("ERROR: Set Affinity Failed!\n");
+ }
+#endif
+#if !(defined RTAI) && !(defined XENOMAI)
+ TimingDesc.dwCpuIndex = dwCpuIndex;
+
+ /* create timing event to trigger the job task */
+ TimingDesc.pvTimingEvent = OsCreateEvent();
+ if( EC_NULL == TimingDesc.pvTimingEvent )
+ {
+ OsDbgMsg("ERROR: insufficient memory to create timing event!\n");
+ goto Exit;
+ }
+
+#if ((defined LINUX) && (defined AUXCLOCK_SUPPORTED))
+ TimingDesc.bUseAuxClock = EC_TRUE;
+#endif /* LINUX && AUXCLOCK_SUPPORTED */
+
+#if (defined AUXCLOCK_SUPPORTED)
+ /* initialize auxiliary clock */
+ if( EC_TRUE == TimingDesc.bUseAuxClock )
+ {
+#if (defined VXWORKS)
+ sysAuxClkDisable();
+ if (OK != sysAuxClkRateSet(1000000 / TimingDesc.dwBusCycleTimeUsec))
+ {
+ OsDbgMsg("Error calling sysAuxClkRateSet!\n");
+ goto Exit;
+ }
+ sysAuxClkConnect((FUNCPTR)vxAuxClkIsr, ((EC_T_INT)TimingDesc.pvTimingEvent));
+ sysAuxClkEnable( );
+ OsSleep(2000);
+
+#elif ((defined UNDER_CE) && (_WIN32_WCE >= 0x600))
+ /* get auxilary clock sysintr */
+ bRes = KernelIoControl((DWORD)IOCTL_AUXCLK_GET_SYSINTR, (DWORD)NULL, (DWORD)0, &dwAuxClkSysIntr, (DWORD)sizeof(DWORD), &dwWinRes);
+ if (!bRes)
+ {
+ OsDbgMsg("Error calling KernelIoControl(IOCTL_AUXCLK_GET_SYSINTR) (0x%08X)!\n", GetLastError());
+ goto Exit;
+ }
+ /* open VirtualDrv for interrupt management */
+ TimingDesc.hVirtualDrv = CreateFile(TEXT("VIR1:"),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ INVALID_HANDLE_VALUE);
+ if ((TimingDesc.hVirtualDrv == NULL) || (TimingDesc.hVirtualDrv == INVALID_HANDLE_VALUE))
+ {
+ OsDbgMsg("Error calling CreateFile(""VIR1:"") (0x%08X)!\n", GetLastError());
+ TimingDesc.hVirtualDrv = NULL;
+ goto Exit;
+ }
+ /* connect auxilary clock interrupt */
+ TimingDesc.oIrqDesc.dwSysIrq = dwAuxClkSysIntr;
+ swprintf(TimingDesc.oIrqDesc.szEventName, TEXT("%s"), TEXT("AUXCLK"));
+ bRes = DeviceIoControl(TimingDesc.hVirtualDrv, (DWORD)IOCTL_VIRTDRV_INTERRUPT_INIT, &(TimingDesc.oIrqDesc), sizeof(VI_T_INTERRUPTDESC), NULL, 0, NULL, NULL );
+ if (!bRes)
+ {
+ OsDbgMsg("Error calling DeviceIoControl(IOCTL_VIRTDRV_INTERRUPT_INIT) (0x%08X)!\n", GetLastError());
+ goto Exit;
+ }
+ /* create auxilary clock interrupt event */
+ TimingDesc.pvAuxClkEvent = (VOID*)CreateEvent(NULL, FALSE, FALSE, TEXT("AUXCLK"));
+ if ((TimingDesc.pvAuxClkEvent == NULL) || (TimingDesc.pvTimingEvent == INVALID_HANDLE_VALUE))
+ {
+ OsDbgMsg("Error creating AuxClk event (0x%08X)!\n", GetLastError());
+ TimingDesc.pvAuxClkEvent = NULL;
+ goto Exit;
+ }
+ /* auxiliary clock event handled within timing task */
+ bStartTimingTask = EC_TRUE;
+
+#elif (defined UNDER_RTSS)
+ hTimer = RtCreateTimer(NULL, 0, RtxAuxClkIsr, (PVOID)TimingDesc.pvTimingEvent, RT_PRIORITY_MAX, CLOCK_2);
+ liTimer.QuadPart = (LONGLONG)10*TimingDesc.dwBusCycleTimeUsec;
+ RtSetTimerRelative(hTimer, &liTimer, &liTimer);
+#else /* !UNDER_RTSS */
+ dwRes = OsAuxClkInit( dwCpuIndex, 1000000 / TimingDesc.dwBusCycleTimeUsec, TimingDesc.pvTimingEvent );
+ if( EC_E_NOERROR != dwRes )
+ {
+ OsDbgMsg( "ERROR at auxiliary clock initialization!\n" );
+ goto Exit;
+ }
+#endif /* !UNDER_RTSS */
+ } // if( EC_TRUE == TimingDesc.bUseAuxClock )
+ else
+#endif
+ {
+#if (defined RTOS_32)
+ CLKSetTimerIntVal( TimingDesc.dwBusCycleTimeUsec );
+ RTKDelay( 1 );
+#endif /* RTOS_32 */
+#if !(defined NO_OS)
+ bStartTimingTask = EC_TRUE;
+#endif /* !NO_OS */
+
+#if (defined EC_VERSION_RTEMS)
+ status = rtems_timer_create(rtems_build_name('E', 'C', 'T', 'T'), &timerId);
+ if(RTEMS_SUCCESSFUL != status)
+ {
+ OsDbgMsg("ATEMDemoMain: cannot create timer\nRTEMS returned: %s\n",
+ rtems_status_text(status));
+ goto Exit;
+ }
+#if (defined RTEMS_USE_TIMER_SERVER)
+ status = rtems_timer_initiate_server(TIMER_THREAD_PRIO,TIMER_THREAD_STACKSIZE,0);
+ if(RTEMS_SUCCESSFUL != status)
+ {
+ OsDbgMsg("ATEMDemoMain: cannot initialise timer\nRTEMS returned: %s\n",
+ rtems_status_text(status));
+ goto Exit;
+ }
+ status = rtems_timer_server_fire_after(timerId,
+ RTEMS_MICROSECONDS_TO_TICKS(TimingDesc.dwBusCycleTimeUsec),
+ rtemsTimerIsr, TimingDesc.pvTimingEvent);
+#else
+ status = rtems_timer_fire_after(timerId,
+ RTEMS_MICROSECONDS_TO_TICKS(TimingDesc.dwBusCycleTimeUsec),
+ rtemsTimerIsr, TimingDesc.pvTimingEvent);
+#endif /* RTEMS_USE_TIMER_SERVER */
+ if(RTEMS_SUCCESSFUL != status)
+ {
+ OsDbgMsg("ATEMDemoMain: cannot initialise timer\nRTEMS returned: %s\n",
+ rtems_status_text(status));
+ goto Exit;
+ }
+ bStartTimingTask = EC_FALSE; //No timing task needed
+#endif /* EC_VERSION_RTEMS */
+ }
+ /* create timing task if needed */
+ if (bStartTimingTask)
+ {
+ OsCreateThread( (EC_T_CHAR*)"tEcTimingTask", (EC_PF_THREADENTRY)tEcTimingTask, TIMER_THREAD_PRIO, LOG_THREAD_STACKSIZE, (EC_T_VOID*)&TimingDesc );
+ while( !TimingDesc.bIsRunning )
+ {
+ OsSleep( 1 );
+ }
+ }
+#endif /* !RTAI && !XENOMAI*/
+ OsDbgMsg( "Run demo now with cycle time %d usec\n", TimingDesc.dwBusCycleTimeUsec);
+#if (defined AUXCLOCK_SUPPORTED)
+ OsDbgMsg("Using %s\n",
+ (TimingDesc.bUseAuxClock ? "AuxClock" : "Sleep"));
+#endif
+ dwRes = ATEMDemo( &oLogging,
+ eCnfType, pbyCnfData, dwCnfDataLen,
+ TimingDesc.dwBusCycleTimeUsec, nVerbose, dwDuration,
+ apLinkParms[0],
+ TimingDesc.pvTimingEvent, dwCpuIndex,
+ bEnaPerfJobs
+#if (defined ATEMRAS_SERVER)
+ ,wServerPort
+#endif
+ ,((2 == dwNumLinkLayer)?apLinkParms[1]:EC_NULL)
+ );
+ if (dwRes != EC_E_NOERROR)
+ {
+ goto Exit;
+ }
+ /* no errors */
+ nRetVal = APP_NOERROR;
+
+Exit:
+ if (nRetVal == SYNTAX_ERROR)
+ {
+ ShowSyntax();
+ }
+ OsDbgMsg("EcMasterDemo stop.\n");
+#if !(defined VXWORKS)
+ if (nRetVal != APP_NOERROR)
+ {
+ OsSleep(5000);
+ }
+#endif
+ /* stop timing task if running */
+#if (defined EC_VERSION_RTEMS)
+ rtems_timer_delete(timerId);
+#else
+ if (EC_TRUE == TimingDesc.bIsRunning)
+ {
+ TimingDesc.bShutdown = EC_TRUE;
+ while( TimingDesc.bIsRunning )
+ {
+ OsSleep( 1 );
+ }
+ }
+#endif
+#if (defined AUXCLOCK_SUPPORTED)
+ /* clean up auxclk */
+ if( TimingDesc.bUseAuxClock )
+ {
+#if (defined EC_VERSION_WINDOWS) || (defined LINUX)
+ OsAuxClkDeinit(0);
+
+#elif (defined VXWORKS)
+ sysAuxClkDisable();
+
+#elif ((defined UNDER_CE) && (_WIN32_WCE >= 0x600))
+ if( NULL != TimingDesc.hVirtualDrv )
+ {
+ /* deinit the auxilary clock interrupt and close the handle to it */
+ TimingDesc.oIrqDesc.dwSysIrq = dwAuxClkSysIntr;
+ bRes = DeviceIoControl(TimingDesc.hVirtualDrv, (DWORD)IOCTL_VIRTDRV_INTERRUPT_DEINIT, &(TimingDesc.oIrqDesc), sizeof(VI_T_INTERRUPTDESC), NULL, 0, NULL, NULL );
+ if (!bRes)
+ {
+ printf("Error calling DeviceIoControl(IOCTL_VIRTDRV_INTERRUPT_DEINIT) (0x%08X)!\n", GetLastError());
+ }
+ CloseHandle(TimingDesc.hVirtualDrv);
+ TimingDesc.hVirtualDrv = NULL;
+ }
+ /* Close the AUXCLK-TimingTask synchronization handle */
+ if( EC_NULL != TimingDesc.pvAuxClkEvent )
+ {
+ CloseHandle(TimingDesc.pvAuxClkEvent);
+ TimingDesc.pvAuxClkEvent = EC_NULL;
+ }
+#elif (defined UNDER_RTSS)
+ if (NULL != hTimer)
+ {
+ RtCancelTimer(hTimer, &liTimer);
+ RtDeleteTimer(hTimer);
+ }
+#endif
+ }
+#endif
+ /* delete the timing event */
+ if( EC_NULL != TimingDesc.pvTimingEvent )
+ {
+ OsDeleteEvent( TimingDesc.pvTimingEvent );
+ TimingDesc.pvTimingEvent = EC_NULL;
+ }
+
+ if (bLogInitialized)
+ {
+ /* de-initialize message logging */
+ oLogging.DeinitLogging();
+ }
+
+ /* final OS layer cleanup */
+ OsDeinit();
+
+ /* free link parms created by CreateLinkParmsFromCmdLine() */
+ for (;dwNumLinkLayer != 0; dwNumLinkLayer--)
+ {
+ if (EC_NULL != apLinkParms[dwNumLinkLayer-1])
+ {
+ OsFree(apLinkParms[dwNumLinkLayer-1]);
+ apLinkParms[dwNumLinkLayer-1] = EC_NULL;
+ }
+ }
+
+#if (defined EC_VERSION_GO32)
+ irq_Close(); /* close the Vortex86 IRQ library */
+ io_Close(); /* close the Vortex86 I/O library */
+#endif
+
+#if (defined EC_VERSION_RTEMS)
+ rtemsSyncBDBuffers();
+ exit(nRetVal);
+#elif !(defined RTAI)
+ return nRetVal;
+#endif
+}
+
+#if (defined EC_VERSION_RTEMS)
+rtems_task Init(rtems_task_argument arg)
+{
+ rtems_id Task_id;
+ rtems_name Task_name = rtems_build_name('M','A','I','N');
+
+ /* read time of day from rtc device and set it to rtems */
+ setRealTimeToRTEMS();
+ /* Mount file systems */
+ rtemsMountFilesystems();
+ /* create and start main task */
+ rtems_task_create(Task_name, MAIN_THREAD_PRIO,
+ RTEMS_MINIMUM_STACK_SIZE * 4, RTEMS_DEFAULT_MODES,
+ RTEMS_FLOATING_POINT | RTEMS_DEFAULT_ATTRIBUTES, &Task_id);
+ rtems_task_start(Task_id, Main, 1);
+// rtems_monitor_init(0);
+ rtems_task_delete( RTEMS_SELF );
+}
+#endif /* EC_VERSION_RTEMS */
+
+/*-Handle static linked link layers -----------------------------------------*/
+#if !defined(ATECAT_DLL)
+#if (defined RTOS_32) || (defined __INTEGRITY) || ((defined __TKERNEL)&& (!defined __arm__)) || (defined __RCX__) || (defined RTAI) || (defined EC_VERSION_ETKERNEL) || (defined EC_VERSION_SYSBIOS) || (defined EC_VERSION_RTEMS)
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+#include "EcLink.h"
+extern EC_T_DWORD emllRegisterI8255x (EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterI8254x (EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterRTL8139(EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterRTL8169(EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterHnx (EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterCPSW (EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterCCAT (EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+extern EC_T_DWORD emllRegisterICSS (EC_T_LINK_DRV_DESC* pLinkDrvDesc, EC_T_DWORD dwLinkDrvDescSize);
+
+EC_PF_LLREGISTER OsGetLinkLayerRegFunc(EC_T_CHAR* szDriverIdent)
+{
+EC_PF_LLREGISTER pfLlRegister = EC_NULL;
+
+#if (defined LINKLAYER_I8254X)
+ if (0 == OsStrcmp("I8254x", szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterI8254x;
+ } else
+#endif
+#if (defined LINKLAYER_I8255X)
+ if (0 == OsStrcmp("I8255x", szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterI8255x;
+ } else
+#endif
+#if (defined LINKLAYER_RTL8139)
+ if (0 == OsStrcmp("RTL8139", szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterRTL8139;
+ } else
+#endif
+#if (defined LINKLAYER_RTL8169)
+ if (0 == OsStrcmp("RTL8169", szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterRTL8169;
+ } else
+#endif
+#if (defined LINKLAYER_HNX)
+ if (0 == OsStrcmp("Hnx", szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterHnx;
+ } else
+#endif
+#if (defined LINKLAYER_FSLFEC)
+ if (0 == OsStrcmp(EC_LINK_PARMS_IDENT_FSLFEC, szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterFslFec;
+ } else
+#endif
+#if (defined LINKLAYER_CPSW)
+ if (0 == OsStrcmp(EC_LINK_PARMS_IDENT_CPSW, szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterCPSW;
+ } else
+#endif
+#if (defined LINKLAYER_ICSS)
+ if (0 == OsStrcmp(EC_LINK_PARMS_IDENT_ICSS, szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterICSS;
+ } else
+#endif
+#if (defined LINKLAYER_CCAT)
+ if (0 == OsStrcmp(EC_LINK_PARMS_IDENT_CCAT, szDriverIdent))
+ {
+ pfLlRegister = (EC_PF_LLREGISTER)emllRegisterCCAT;
+ } else
+#endif
+ {
+ pfLlRegister = EC_NULL;
+ }
+ return pfLlRegister;
+}
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+#endif /* RTOS_32 || __INTEGRITY || __TKERNEL || __RCX__ || RTAI */
+#endif /* !ATECAT_DLL */
+
+/*-END OF SOURCE FILE--------------------------------------------------------*/
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/Logging.cpp b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/Logging.cpp
--- /dev/null
@@ -0,0 +1,1263 @@
+/*-----------------------------------------------------------------------------
+ * Logging.cpp
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description EtherCAT Master application logging
+ *---------------------------------------------------------------------------*/
+
+/*-INCLUDES------------------------------------------------------------------*/
+#include "Logging.h"
+#include "EcError.h"
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef VXWORKS
+#include "vxWorks.h"
+#include "sysLib.h"
+#include "tickLib.h"
+#if ((defined _WRS_VXWORKS_MAJOR) && (defined _WRS_VXWORKS_MINOR) && ( (_WRS_VXWORKS_MAJOR >= 7) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 5)) ))
+#else
+#include <ifLib.h>
+#endif
+#endif /* VXWORKS */
+
+#if (defined __MET__)
+#include <ConfigerTasks.h>
+#endif
+
+/*-MACROS--------------------------------------------------------------------*/
+/*#define NOPRINTF 1*/
+
+/*-DEFINES-------------------------------------------------------------------*/
+#if !(defined EC_DEMO_TINY)
+
+#define MAX_MESSAGE_SIZE 256 /* maximum size of a single message */
+#define DEFAULT_ERR_MSG_BUFFER_SIZE 500 /* number of buffered messages */
+#define DEFAULT_LOG_MSG_BUFFER_SIZE 1000 /* number of buffered messages */
+#define DEFAULT_DCM_MSG_BUFFER_SIZE 1000 /* number of buffered messages */
+
+#else
+
+#define MAX_MESSAGE_SIZE 100 /* maximum size of a single message */
+#define DEFAULT_ERR_MSG_BUFFER_SIZE 20 /* number of buffered messages */
+#define DEFAULT_LOG_MSG_BUFFER_SIZE 30 /* number of buffered messages */
+#define DEFAULT_DCM_MSG_BUFFER_SIZE 4 /* number of buffered messages */
+
+#endif /* !(defined EC_DEMO_TINY) */
+
+#if (defined UNDER_RTSS) || (defined __INTIME__)
+ #define ABSOLUTE_LOG_FILE_PATH "C:\\"
+#else
+ #define ABSOLUTE_LOG_FILE_PATH ""
+#endif
+#if (defined EC_VERSION_ECOS)
+ #define FILESYS_8_3
+#endif
+
+#ifdef FILESYS_8_3
+#define REM_ERRLOG_FILNAM "rer"
+#define LOC_ERRLOG_FILNAM "er"
+#define REM_MASTER_LOG_FILNAM "rma"
+#define LOC_MASTER_LOG_FILNAM "ma"
+#define REM_DCM_LOG_FILNAM "rdc"
+#define LOC_DCM_LOG_FILNAM "dc"
+#else
+#define REM_ERRLOG_FILNAM "rerror"
+#define LOC_ERRLOG_FILNAM (EC_T_CHAR*)"error"
+#define REM_MASTER_LOG_FILNAM "recmaster"
+#define LOC_MASTER_LOG_FILNAM (EC_T_CHAR*)"ecmaster"
+#define REM_DCM_LOG_FILNAM "rdcmlog"
+#define LOC_DCM_LOG_FILNAM (EC_T_CHAR*)"dcmlog"
+#endif
+
+#if (defined INCLUDE_ATEMRAS)
+#define ERRLOG_FILNAM REM_ERRLOG_FILNAM
+#define MASTER_LOG_FILNAM REM_MASTER_LOG_FILNAM
+#define DCM_LOG_FILNAM REM_DCM_LOG_FILNAM
+#else
+#define ERRLOG_FILNAM LOC_ERRLOG_FILNAM
+#define MASTER_LOG_FILNAM LOC_MASTER_LOG_FILNAM
+#define DCM_LOG_FILNAM LOC_DCM_LOG_FILNAM
+#endif
+
+
+/*-GLOBAL VARIABLES-----------------------------------------------------------*/
+#if (defined VXWORKS) || (defined __TKERNEL) || (defined RTAI)\
+ || (defined EC_VERSION_SYSBIOS) || (defined EC_VERSION_RIN32M3) || (defined EC_VERSION_XILINX_STANDALONE)\
+ || (defined EC_VERSION_ETKERNEL) || (defined EC_VERSION_RZT1) || (defined EC_VERSION_RZGNOOS) || (defined EC_VERSION_ECOS)
+EC_T_BOOL bLogFileEnb = EC_FALSE;
+#else
+EC_T_BOOL bLogFileEnb = EC_TRUE;
+#endif
+
+/*-LOCAL VARIABLES-----------------------------------------------------------*/
+
+CAtEmLogging* G_pOsDbgMsgLoggingInst = EC_NULL;
+
+
+/*-FORWARD DECLARATIONS------------------------------------------------------*/
+
+
+/***************************************************************************************************/
+/**
+\brief Create CAtEmLogging instance
+
+\return -
+*/
+CAtEmLogging::CAtEmLogging(EC_T_VOID)
+{
+ m_pvLogThreadObj = EC_NULL;
+ m_bLogTaskRunning = EC_FALSE;
+ m_bShutdownLogTask = EC_FALSE;
+ m_bDbgMsgHookEnable = EC_TRUE;
+ m_bSettling = EC_FALSE;
+ m_dwNumMsgsSinceMsrmt = 0;
+ m_poInsertMsgLock = EC_NULL;
+ m_poProcessMsgLock = EC_NULL;
+ m_pchTempbuffer = EC_NULL;
+ m_pFirstMsgBufferDesc = EC_NULL;
+ m_pLastMsgBufferDesc = EC_NULL;
+ m_pAllMsgBufferDesc = EC_NULL;
+ m_pErrorMsgBufferDesc = EC_NULL;
+ m_pDcmMsgBufferDesc = EC_NULL;
+ m_pchLogDir[0] = '\0';
+ m_pchLogDir[MAX_PATH_LEN - 1] = '\0';
+}
+
+
+/********************************************************************************/
+/** \brief Initialize logging
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::InitLogging(
+ EC_T_DWORD dwMasterID,
+ EC_T_WORD wRollOver,
+ EC_T_DWORD dwPrio,
+ EC_T_DWORD dwCpuIndex,
+ EC_T_CHAR* szFilenamePrefix,
+ EC_T_DWORD dwStackSize
+ )
+{
+ EC_T_CPUSET CpuSet;
+#if !(defined XENOMAI)
+ EC_T_BOOL bOk;
+#endif
+ EC_T_CHAR szLogFilename[256];
+
+ if (EC_NULL == G_pOsDbgMsgLoggingInst )
+ {
+ G_pOsDbgMsgLoggingInst = this;
+ }
+ m_poInsertMsgLock = OsCreateLockTyped(eLockType_SPIN);
+ m_poProcessMsgLock = OsCreateLock();
+ m_pchTempbuffer = (EC_T_CHAR*)OsMalloc(2*MAX_MESSAGE_SIZE);
+ if (EC_NULL == m_pchTempbuffer)
+ {
+ LogError("InitLogging: not enough memory for m_pchTempbuffer\n");
+ }
+
+ /* zero-terminate log msg (snprintf doesn't include this) */
+ m_pchTempbuffer[0] = '\0';
+ m_pchTempbuffer[2*MAX_MESSAGE_SIZE - 1] = '\0';
+
+ if ((EC_NULL != szFilenamePrefix) && ('\0' != szFilenamePrefix[0]))
+ {
+ OsSnprintf(szLogFilename, sizeof(szLogFilename) - 1, "%s_err", szFilenamePrefix);
+ }
+ else
+ {
+ OsSnprintf(szLogFilename, sizeof(szLogFilename) - 1, "%s", ERRLOG_FILNAM);
+ }
+ m_pErrorMsgBufferDesc = (MSG_BUFFER_DESC*)AddLogBuffer(
+ dwMasterID,
+ wRollOver,
+ DEFAULT_ERR_MSG_BUFFER_SIZE,
+ EC_TRUE, /* skip duplicates */
+ (EC_T_CHAR*)"Err", /* name of the logging (identification) */
+ szLogFilename,
+ (EC_T_CHAR*)"log", /* log file extension */
+ EC_FALSE, /* print message on console? */
+ EC_TRUE ); /* logging with time stamp? */
+ if (EC_NULL == m_pErrorMsgBufferDesc)
+ {
+ LogError("InitLogging: not enough memory for m_pErrorMsgBufferDesc\n");
+ }
+
+ if ((EC_NULL != szFilenamePrefix) && ('\0' != szFilenamePrefix[0]))
+ {
+ OsSnprintf(szLogFilename, sizeof(szLogFilename) - 1, "%s", szFilenamePrefix);
+ }
+ else
+ {
+ OsSnprintf(szLogFilename, sizeof(szLogFilename) - 1, "%s", MASTER_LOG_FILNAM);
+ }
+ m_pAllMsgBufferDesc = (MSG_BUFFER_DESC*)AddLogBuffer(
+ dwMasterID,
+ wRollOver,
+ DEFAULT_LOG_MSG_BUFFER_SIZE,
+ EC_TRUE, /* skip duplicates */
+ (EC_T_CHAR*)"Log", /* name of the logging (identification) */
+ szLogFilename,
+ (EC_T_CHAR*)"log", /* log file extension */
+ EC_TRUE, /* print message on console? */
+ EC_TRUE ); /* logging with time stamp? */
+ if (EC_NULL == m_pAllMsgBufferDesc)
+ {
+ LogError("InitLogging: not enough memory for m_pAllMsgBufferDesc\n");
+ }
+
+ if ((EC_NULL != szFilenamePrefix) && ('\0' != szFilenamePrefix[0]))
+ {
+ OsSnprintf(szLogFilename, sizeof(szLogFilename) - 1, "%s_dcm", szFilenamePrefix);
+ }
+ else
+ {
+ OsSnprintf(szLogFilename, sizeof(szLogFilename) - 1, "%s", DCM_LOG_FILNAM);
+ }
+ m_pDcmMsgBufferDesc = (MSG_BUFFER_DESC*)AddLogBuffer(
+ dwMasterID,
+ wRollOver,
+ DEFAULT_DCM_MSG_BUFFER_SIZE,
+ EC_FALSE, /* do not skip duplicates */
+ (EC_T_CHAR*)"DCM", /* name of the logging (identification) */
+ szLogFilename,
+ (EC_T_CHAR*)"csv", /* log file extension */
+ EC_FALSE, /* print message on console? */
+ EC_FALSE ); /* logging with time stamp? */
+ if (EC_NULL == m_pDcmMsgBufferDesc)
+ {
+ LogError("InitLogging: not enough memory for m_pDcmMsgBufferDesc\n");
+ }
+
+ OsDbgAssert(!m_bLogTaskRunning);
+ m_bShutdownLogTask = EC_FALSE;
+ EC_CPUSET_ZERO(CpuSet);
+ EC_CPUSET_SET(CpuSet, dwCpuIndex);
+#ifndef NO_OS
+#if (defined __MET__)
+ m_pvLogThreadObj = (EC_T_VOID*)_task_create((EC_T_WORD)0, (EC_T_DWORD)TECAT_LOGGING_INDEX, (EC_T_DWORD)this);
+#elif (defined XENOMAI)
+ /* for Xenomai, pass the CPU affinity as upper 16bit of thread priority */
+ m_pvLogThreadObj = OsCreateThread( (EC_T_CHAR*)"tAtEmLog", tAtEmLogWrapper, (CpuSet << 16) | dwPrio, dwStackSize, this );
+#else
+ m_pvLogThreadObj = OsCreateThread( (EC_T_CHAR*)"tAtEmLog", tAtEmLogWrapper, dwPrio, dwStackSize, this );
+#endif
+ while (!m_bLogTaskRunning) OsSleep(1);
+#endif
+
+#if !(defined XENOMAI)
+ /* for Xenomai, the CPU affinity is set during task creating, see above */
+ bOk = OsSetThreadAffinity( m_pvLogThreadObj, CpuSet );
+ if (!bOk)
+ {
+ LogError("Error: Set log task affinitiy, invalid CPU index %d\n", 0);
+ }
+#endif /* !XENOMAI */
+}
+
+/********************************************************************************/
+/** \brief Initialize logging
+*
+* \return message buffer descriptor
+*/
+struct _MSG_BUFFER_DESC* CAtEmLogging::AddLogBuffer(
+ EC_T_DWORD dwMasterID,
+ EC_T_WORD wRollOver,
+ EC_T_DWORD dwBufferSize, /* [in] buffer size (number of buffered messages) */
+ EC_T_BOOL bSkipDuplicates, /* [in] EC_TRUE if duplicate messages shall be skipped */
+ EC_T_CHAR* szLogName, /* [in] name of the logging (identification) */
+ EC_T_CHAR* szLogFilename, /* [in] log filename */
+ EC_T_CHAR* szLogFileExt, /* [in] log file extension */
+ EC_T_BOOL bPrintConsole, /* [in] print message on console? */
+ EC_T_BOOL bPrintTimestamp /* [in] logging with time stamp? */
+ )
+{
+ EC_T_CHAR szLogFileNameTmp[MAX_PATH_LEN];
+ MSG_BUFFER_DESC* pNewMsgBufferDesc = EC_NULL;
+ EC_T_BOOL bLocked = EC_FALSE;
+ EC_T_BOOL bOk = EC_FALSE;
+
+ OsLock( m_poProcessMsgLock );
+ bLocked = EC_TRUE;
+
+ /* create buffers */
+ pNewMsgBufferDesc = (MSG_BUFFER_DESC*)OsMalloc(sizeof(MSG_BUFFER_DESC));
+ if (pNewMsgBufferDesc == EC_NULL )
+ {
+ LogError( "AddLogBuffer: cannot allocate message buffer descriptor\n" );
+ goto Exit;
+ }
+ OsMemset(pNewMsgBufferDesc, 0, sizeof(MSG_BUFFER_DESC));
+
+ if (m_pchLogDir[0] != '\0')
+ {
+ OsSnprintf(szLogFileNameTmp, sizeof(szLogFileNameTmp)-1, "%s%s%d", m_pchLogDir, szLogFilename, dwMasterID);
+ }
+ else
+ {
+ OsSnprintf(szLogFileNameTmp, sizeof(szLogFileNameTmp)-1, "%s%s%d", ABSOLUTE_LOG_FILE_PATH, szLogFilename, dwMasterID);
+ }
+ bOk = InitMsgBuffer( pNewMsgBufferDesc,
+ MAX_MESSAGE_SIZE,
+ dwBufferSize,
+ bSkipDuplicates,
+ bPrintConsole,
+ bPrintTimestamp,
+ szLogFileNameTmp,
+ szLogFileExt,
+ wRollOver,
+ szLogName
+ );
+ if (!bOk)
+ {
+ goto Exit;
+ }
+
+ /* link buffer together */
+ if (m_pLastMsgBufferDesc == EC_NULL )
+ {
+ /* create first buffer */
+ OsDbgAssert( m_pFirstMsgBufferDesc == EC_NULL );
+ m_pFirstMsgBufferDesc = m_pLastMsgBufferDesc = pNewMsgBufferDesc;
+ pNewMsgBufferDesc->pNextMsgBuf = EC_NULL;
+ }
+ else
+ {
+ /* append to last buffer */
+ OsDbgAssert( m_pLastMsgBufferDesc->pNextMsgBuf == EC_NULL );
+ m_pLastMsgBufferDesc->pNextMsgBuf = pNewMsgBufferDesc;
+ m_pLastMsgBufferDesc = pNewMsgBufferDesc;
+ }
+ bOk = EC_TRUE;
+
+Exit:
+ if (!bOk)
+ {
+ if (pNewMsgBufferDesc!=EC_NULL) OsFree(pNewMsgBufferDesc);
+ pNewMsgBufferDesc = EC_NULL;
+ }
+
+ if (bLocked)
+ OsUnlock( m_poProcessMsgLock );
+ return pNewMsgBufferDesc;
+}
+
+
+/********************************************************************************/
+/** \brief set log message buffer
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::SetMsgBuf(
+ MSG_BUFFER_DESC* pMsgBufferDesc,
+ EC_T_BYTE* pbyLogMem,
+ EC_T_DWORD dwSize )
+{
+ pMsgBufferDesc->pbyNextLogMsg = pbyLogMem;
+ pMsgBufferDesc->dwLogMemorySize = dwSize;
+ pMsgBufferDesc->bLogBufferFull = EC_FALSE;
+ pMsgBufferDesc->bNewLine = EC_TRUE;
+ OsMemset(pbyLogMem, 0, dwSize);
+ pMsgBufferDesc->pbyLogMemory = pbyLogMem; /* initialize last as it will be active immediately after! */
+}
+EC_T_VOID CAtEmLogging::SetLogMsgBuf( EC_T_BYTE* pbyLogMem, EC_T_DWORD dwSize )
+{
+ SetMsgBuf( m_pAllMsgBufferDesc, pbyLogMem, dwSize );
+}
+EC_T_VOID CAtEmLogging::SetLogErrBuf( EC_T_BYTE* pbyLogMem, EC_T_DWORD dwSize )
+{
+ SetMsgBuf( m_pErrorMsgBufferDesc, pbyLogMem, dwSize );
+}
+EC_T_VOID CAtEmLogging::SetLogDcmBuf( EC_T_BYTE* pbyLogMem, EC_T_DWORD dwSize )
+{
+ SetMsgBuf( m_pDcmMsgBufferDesc, pbyLogMem, dwSize );
+}
+
+/********************************************************************************/
+/** \brief De-initialize logging
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::DeinitLogging( EC_T_VOID )
+{
+MSG_BUFFER_DESC* pCurrMsgBuf;
+MSG_BUFFER_DESC* pNextMsgBuf;
+
+ if (G_pOsDbgMsgLoggingInst == this)
+ {
+ G_pOsDbgMsgLoggingInst = EC_NULL;
+ }
+
+ m_bShutdownLogTask = EC_TRUE;
+
+ while (m_bLogTaskRunning) OsSleep(1);
+
+ /* shutdown all message buffers */
+ pNextMsgBuf = m_pFirstMsgBufferDesc;
+ while (EC_NULL != pNextMsgBuf)
+ {
+ DeinitMsgBuffer(pNextMsgBuf);
+ pNextMsgBuf = pNextMsgBuf->pNextMsgBuf;
+ }
+
+#if (defined __MET__)
+ _task_destroy( (_task_id) m_pvLogThreadObj);
+#else
+ OsDeleteThreadHandle(m_pvLogThreadObj);
+#endif
+
+ m_pvLogThreadObj = EC_NULL;
+
+ /* free all message buffers */
+ pNextMsgBuf = m_pFirstMsgBufferDesc;
+ while (EC_NULL != pNextMsgBuf)
+ {
+ pCurrMsgBuf = pNextMsgBuf;
+ pNextMsgBuf = pCurrMsgBuf->pNextMsgBuf;
+ OsFree(pCurrMsgBuf);
+ }
+ /* unlink buffers */
+ m_pFirstMsgBufferDesc = EC_NULL;
+ m_pLastMsgBufferDesc = EC_NULL;
+ m_pAllMsgBufferDesc = EC_NULL;
+ m_pErrorMsgBufferDesc = EC_NULL;
+ m_pDcmMsgBufferDesc = EC_NULL;
+
+ OsDeleteLock(m_poInsertMsgLock);
+ OsDeleteLock(m_poProcessMsgLock);
+ SafeOsFree(m_pchTempbuffer);
+ m_pchTempbuffer = EC_NULL;
+}
+
+
+/********************************************************************************/
+/** \brief logging thread
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::tAtEmLogWrapper(EC_T_VOID* pvParm)
+{
+ CAtEmLogging *pInst = (CAtEmLogging*)pvParm;
+
+ OsDbgAssert(EC_NULL != pInst);
+ if (pInst)
+ {
+ pInst->tAtEmLog(EC_NULL);
+ }
+}
+
+
+/********************************************************************************/
+/** \brief cyclically process all messages
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::tAtEmLog(EC_T_VOID* pvParm)
+{
+ EC_UNREFPARM(pvParm);
+
+ m_bLogTaskRunning = EC_TRUE;
+ while (!m_bShutdownLogTask)
+ {
+ ProcessAllMsgs();
+ OsSleep(1);
+ }
+ ProcessAllMsgs();
+ m_bLogTaskRunning = EC_FALSE;
+#if (defined EC_VERSION_RTEMS)
+ rtems_task_delete(RTEMS_SELF);
+#endif
+}
+
+EC_T_VOID CAtEmLogging::ProcessAllMsgs(EC_T_VOID)
+{
+MSG_BUFFER_DESC* pNextMsgBuf;
+
+ pNextMsgBuf = m_pFirstMsgBufferDesc;
+ while (EC_NULL != pNextMsgBuf)
+ {
+ ProcessMsgs(pNextMsgBuf);
+ pNextMsgBuf = pNextMsgBuf->pNextMsgBuf;
+ }
+}
+
+/********************************************************************************/
+/** \brief Initialize message buffer
+*
+* \return N/A
+*/
+EC_T_BOOL CAtEmLogging::InitMsgBuffer
+(MSG_BUFFER_DESC* pMsgBufferDesc /* [in] pointer to message buffer descriptor */
+,EC_T_DWORD dwMsgSize /* [in] size of a single message */
+,EC_T_DWORD dwNumMsgs /* [in] number of messages */
+,EC_T_BOOL bSkipDuplicates /* [in] EC_TRUE if duplicate messages shall be skipped */
+,EC_T_BOOL bPrintConsole /* [in] print message on console? */
+,EC_T_BOOL bPrintTimestamp /* [in] logging with time stamp? */
+,EC_T_CHAR* szMsgLogFileName /* [in] message log file name */
+,EC_T_CHAR* szMsgLogFileExt /* [in] message log file name */
+,EC_T_WORD wRollOver /* [in] roll over counter */
+,EC_T_CHAR* szBufferName /* [in] name of the logging buffer */
+)
+{
+ EC_T_BOOL bOk = EC_FALSE;
+ EC_T_CHAR* pchMsgBuffer = EC_NULL;
+ EC_T_DWORD dwBufSiz;
+ EC_T_DWORD dwCnt;
+#if (!(defined __RCX__) || (defined __MET__)) && !(defined RTAI)
+ EC_T_CHAR szfileNameTemp[MAX_PATH_LEN] = {0};
+#endif
+
+ pMsgBufferDesc->dwMsgSize = dwMsgSize;
+ pMsgBufferDesc->dwNumMsgs = dwNumMsgs;
+ pMsgBufferDesc->bPrintTimestamp = bPrintTimestamp;
+ pMsgBufferDesc->bPrintConsole = bPrintConsole;
+ pMsgBufferDesc->dwNextEmptyMsgIndex = 0;
+ pMsgBufferDesc->dwNextPrintMsgIndex = 0;
+ pMsgBufferDesc->wEntryCounter = 0;
+ pMsgBufferDesc->pbyLogMemory = EC_NULL;
+ pMsgBufferDesc->dwLogMemorySize = 0;
+ pMsgBufferDesc->pbyNextLogMsg = EC_NULL;
+ pMsgBufferDesc->bLogBufferFull = EC_FALSE;
+ pMsgBufferDesc->bSkipDuplicateMessages = bSkipDuplicates;
+ pMsgBufferDesc->dwNumDuplicates = 0;
+ pMsgBufferDesc->pszLastMsg = EC_NULL;
+
+ pMsgBufferDesc->paMsg = (LOG_MSG_DESC*)OsMalloc(dwNumMsgs*sizeof(LOG_MSG_DESC));
+ if (pMsgBufferDesc->paMsg == EC_NULL)
+ {
+ OsPrintf("CAtEmLogging::InitMsgBuffer: cannot get memory for logging buffer '%s'\n", szBufferName);
+ goto Exit;
+ }
+ OsMemset(pMsgBufferDesc->paMsg, 0, dwNumMsgs*sizeof(LOG_MSG_DESC));
+
+ dwBufSiz = dwNumMsgs * (dwMsgSize + 1);
+ pchMsgBuffer = (EC_T_CHAR*)OsMalloc(dwBufSiz);
+ if (pchMsgBuffer == EC_NULL)
+ {
+ OsPrintf("CAtEmLogging::InitMsgBuffer: cannot get memory for logging buffer '%s'\n", szBufferName);
+ goto Exit;
+ }
+
+ /* Same as below. Needed to prevent false positive from static code analysis. */
+ pMsgBufferDesc->paMsg[0].szMsgBuffer = pchMsgBuffer;
+
+ OsMemset(pchMsgBuffer,0,dwBufSiz);
+ for( dwCnt=0; dwCnt < dwNumMsgs; dwCnt++ )
+ {
+ pMsgBufferDesc->paMsg[dwCnt].szMsgBuffer = &pchMsgBuffer[dwCnt*(dwMsgSize+1)];
+ pMsgBufferDesc->paMsg[dwCnt].bMsgCrLf = EC_TRUE;
+ }
+
+#if (defined __RCX__) || (defined __MET__) || (defined RTAI)
+ pMsgBufferDesc->pfMsgFile = EC_NULL;
+#else
+ pMsgBufferDesc->wLogFileIndex = 0;
+ pMsgBufferDesc->wEntryCounterLimit = wRollOver;
+ OsStrncpy(pMsgBufferDesc->szMsgLogFileName, szMsgLogFileName, sizeof(pMsgBufferDesc->szMsgLogFileName) - 1);
+ OsStrncpy(pMsgBufferDesc->szMsgLogFileExt, szMsgLogFileExt, sizeof(pMsgBufferDesc->szMsgLogFileExt) - 1);
+
+ if (0 != pMsgBufferDesc->wEntryCounterLimit )
+ {
+#ifdef FILESYS_8_3
+ OsSnprintf(szfileNameTemp, sizeof(szfileNameTemp) - 1, "%s_%x.%s", pMsgBufferDesc->szMsgLogFileName, pMsgBufferDesc->wLogFileIndex, pMsgBufferDesc->szMsgLogFileExt);
+#else
+ OsSnprintf(szfileNameTemp, sizeof(szfileNameTemp) - 1, "%s.%x.%s", pMsgBufferDesc->szMsgLogFileName, pMsgBufferDesc->wLogFileIndex, pMsgBufferDesc->szMsgLogFileExt);
+#endif
+ }
+ else
+ {
+ OsSnprintf(szfileNameTemp, sizeof(szfileNameTemp) - 1, "%s.%s", pMsgBufferDesc->szMsgLogFileName, pMsgBufferDesc->szMsgLogFileExt);
+ }
+
+ if (bLogFileEnb)
+ {
+ pMsgBufferDesc->pfMsgFile = OsFopen( szfileNameTemp, "w+" );
+ if (pMsgBufferDesc->pfMsgFile == EC_NULL )
+ {
+#if !(defined NOPRINTF)
+ OsPrintf( "ERROR: cannot create EtherCAT log file %s\n", szfileNameTemp );
+#endif
+ OsSleep(3000);
+ }
+ }
+ else
+ {
+ pMsgBufferDesc->pfMsgFile = EC_NULL;
+ pMsgBufferDesc->szMsgLogFileName[0] = 0;
+ }
+ OsStrncpy(pMsgBufferDesc->szLogName, szBufferName, MAX_PATH_LEN - 1);
+
+#endif
+ pMsgBufferDesc->bIsInitialized = EC_TRUE;
+ bOk = EC_TRUE;
+
+Exit:
+ if (!bOk)
+ {
+ if (pMsgBufferDesc->paMsg!=EC_NULL)
+ {
+ OsFree(pMsgBufferDesc->paMsg);
+ }
+ if (pchMsgBuffer == EC_NULL)
+ {
+ OsFree(pchMsgBuffer);
+ }
+ }
+ return bOk;
+}
+
+
+/********************************************************************************/
+/** \brief De-Init message buffer
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::DeinitMsgBuffer
+(MSG_BUFFER_DESC* pMsgBufferDesc
+)
+{
+CEcTimer oTimeout;
+
+ if (pMsgBufferDesc->bIsInitialized)
+ {
+ /* let the log task print out all messages */
+ if (pMsgBufferDesc->dwNextPrintMsgIndex != pMsgBufferDesc->dwNextEmptyMsgIndex)
+ {
+ OsPrintf("Store unsaved messages in '%s' message/logging buffer...", pMsgBufferDesc->szLogName);
+ oTimeout.Start(3000);
+ while (pMsgBufferDesc->dwNextPrintMsgIndex != pMsgBufferDesc->dwNextEmptyMsgIndex)
+ {
+ ProcessAllMsgs();
+ OsSleep(100);
+ if (oTimeout.IsElapsed())
+ {
+ OsPrintf(".");
+ oTimeout.Start(3000);
+ }
+ }
+ OsPrintf(" done!\n");
+ }
+
+ OsFree(pMsgBufferDesc->paMsg[0].szMsgBuffer);
+ OsFree(pMsgBufferDesc->paMsg);
+
+ if (EC_NULL != pMsgBufferDesc->pfMsgFile)
+ {
+ OsFclose(pMsgBufferDesc->pfMsgFile);
+ }
+
+ pMsgBufferDesc->pfMsgFile = EC_NULL;
+ pMsgBufferDesc->dwNextEmptyMsgIndex = 0;
+ pMsgBufferDesc->dwNextPrintMsgIndex = 0;
+ pMsgBufferDesc->bIsInitialized = EC_FALSE;
+ pMsgBufferDesc->pbyLogMemory = EC_NULL;
+ pMsgBufferDesc->dwLogMemorySize = 0;
+ pMsgBufferDesc->pbyNextLogMsg = EC_NULL;
+ pMsgBufferDesc->bLogBufferFull = EC_FALSE;
+ pMsgBufferDesc->pszLastMsg = EC_NULL;
+ }
+}
+
+/********************************************************************************/
+/** \brief Insert a new message into message buffer
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::InsertNewMsg
+(MSG_BUFFER_DESC* pMsgBufferDesc
+,const
+ EC_T_CHAR* szFormat
+,EC_T_VALIST vaArgs
+,EC_T_BOOL bDoCrLf
+,EC_T_BOOL bOsDbgMsg
+)
+{
+ EC_T_DWORD dwRes = EC_E_NOERROR;
+ EC_T_BOOL bBufferFull = EC_FALSE;
+ EC_T_DWORD dwTimeStamp = 0;
+ LOG_MSG_DESC* pNewMsg = EC_NULL;
+
+ if (pMsgBufferDesc == EC_NULL )
+ goto Exit;
+ if (!pMsgBufferDesc->bIsInitialized)
+ {
+ dwRes = EC_E_INVALIDSTATE;
+ goto Exit;
+ }
+
+ if (m_bShutdownLogTask )
+ goto Exit;
+
+ OsLock(m_poInsertMsgLock);
+ {
+ EC_T_DWORD dwNewNextEmpty = 0;
+
+ pNewMsg = &pMsgBufferDesc->paMsg[pMsgBufferDesc->dwNextEmptyMsgIndex];
+
+ dwNewNextEmpty = pMsgBufferDesc->dwNextEmptyMsgIndex + 1;
+ if (dwNewNextEmpty >= pMsgBufferDesc->dwNumMsgs )
+ {
+ dwNewNextEmpty = 0;
+ }
+
+ /* check if message buffer is full ? */
+ if (dwNewNextEmpty == pMsgBufferDesc->dwNextPrintMsgIndex )
+ {
+ bBufferFull = EC_TRUE;
+ }
+ else
+ {
+ pMsgBufferDesc->dwNextEmptyMsgIndex = dwNewNextEmpty;
+ }
+ }
+ OsUnlock(m_poInsertMsgLock);
+
+
+ if (bBufferFull)
+ {
+ dwRes = EC_E_NOMEMORY;
+ goto Exit;
+ }
+
+
+ if (pMsgBufferDesc->bPrintTimestamp )
+ {
+ dwTimeStamp = OsQueryMsecCount();
+ }
+ pNewMsg->dwMsgTimestamp = dwTimeStamp;
+ pNewMsg->bOsDbgMsg = bOsDbgMsg;
+ pNewMsg->bMsgCrLf = bDoCrLf;
+
+ pNewMsg->dwLen = EcVsnprintf(pNewMsg->szMsgBuffer, pMsgBufferDesc->dwMsgSize, szFormat,vaArgs);
+
+ /* mark entry as complete */
+ OsMemoryBarrier();
+ pNewMsg->bValid = EC_TRUE;
+
+Exit:
+ return dwRes;
+}
+
+
+/********************************************************************************/
+/** \brief Forward to next logging buffer (memory logging)
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::SelectNextLogMemBuffer
+(MSG_BUFFER_DESC* pMsgBufferDesc )
+{
+ pMsgBufferDesc->pbyNextLogMsg = pMsgBufferDesc->pbyNextLogMsg + OsStrlen(pMsgBufferDesc->pbyNextLogMsg);
+ if (pMsgBufferDesc->pbyNextLogMsg >= (pMsgBufferDesc->pbyLogMemory + pMsgBufferDesc->dwLogMemorySize - 3*MAX_MESSAGE_SIZE) )
+ {
+ /* stop logging if memory is full */
+ OsDbgMsg( "logging buffer %s is full, logging stopped!\n", pMsgBufferDesc->szLogName );
+ pMsgBufferDesc->bLogBufferFull = EC_TRUE;
+ }
+
+ /* zero-terminate log msg (snprintf doesn't include this) */
+ pMsgBufferDesc->pbyNextLogMsg[0] = '\0';
+ pMsgBufferDesc->pbyNextLogMsg[MAX_MESSAGE_SIZE - 1] = '\0';
+}
+
+/********************************************************************************/
+/** \brief Process all messages of a message buffer
+*
+* \return N/A
+*/
+EC_T_VOID CAtEmLogging::ProcessMsgs
+(MSG_BUFFER_DESC* pMsgBufferDesc )
+{
+ EC_T_DWORD dwNewNextPrint=0;
+ LOG_MSG_DESC* pCurrMsg = EC_NULL;
+ EC_T_BOOL bLocked = EC_FALSE;
+#if (!(defined __RCX__) || (defined __MET__)) && !(defined RTAI)
+ FILE* pFileHandle = EC_NULL;
+ EC_T_BOOL bRollOver = EC_FALSE;
+ EC_T_CHAR szfileNameTemp[MAX_PATH_LEN];
+#endif
+ EC_T_DWORD dwNumMsgLeft = 20;
+ EC_T_BOOL bSkipDuplicate;
+ EC_T_DWORD dwNumDuplicatesBeforeNewMsg;
+
+ szfileNameTemp[0] = '\0';
+
+ if (pMsgBufferDesc->bIsInitialized )
+ {
+ OsLock(m_poProcessMsgLock);
+ bLocked = EC_TRUE;
+ while( pMsgBufferDesc->dwNextPrintMsgIndex != pMsgBufferDesc->dwNextEmptyMsgIndex )
+ {
+ OsDbgAssert(pMsgBufferDesc->bIsInitialized);
+
+ // return after maximum number of processed messages
+ if (dwNumMsgLeft == 0 )
+ break;
+
+ pCurrMsg = &pMsgBufferDesc->paMsg[pMsgBufferDesc->dwNextPrintMsgIndex];
+ /* wait til message is complete */
+ if (!pCurrMsg->bValid)
+ {
+ break;
+ }
+
+#if (!(defined __RCX__) || (defined __MET__)) && !(defined RTAI)
+ if (bLogFileEnb && (pMsgBufferDesc->pfMsgFile != EC_NULL) )
+ {
+ pFileHandle = pMsgBufferDesc->pfMsgFile;
+
+ pMsgBufferDesc->wEntryCounter++;
+ if (0 != pMsgBufferDesc->wEntryCounterLimit && pMsgBufferDesc->pfMsgFile != EC_NULL )
+ {
+ if (pMsgBufferDesc->wEntryCounter >= pMsgBufferDesc->wEntryCounterLimit )
+ {
+ bRollOver = EC_TRUE;
+ pMsgBufferDesc->wEntryCounter = 0;
+ pMsgBufferDesc->wLogFileIndex++;
+
+#ifdef FILESYS_8_3
+ OsSnprintf(szfileNameTemp, sizeof(szfileNameTemp) - 1, "%s_%x.%s", pMsgBufferDesc->szMsgLogFileName, pMsgBufferDesc->wLogFileIndex, pMsgBufferDesc->szMsgLogFileExt);
+#else
+ OsSnprintf(szfileNameTemp, sizeof(szfileNameTemp) - 1, "%s.%x.%s", pMsgBufferDesc->szMsgLogFileName, pMsgBufferDesc->wLogFileIndex, pMsgBufferDesc->szMsgLogFileExt);
+#endif
+ }
+ else
+ {
+ bRollOver = EC_FALSE;
+ }
+
+ }
+ }
+#endif
+
+ /* handle skipping duplicates */
+ bSkipDuplicate = EC_FALSE;
+ dwNumDuplicatesBeforeNewMsg = 0;
+ if (pMsgBufferDesc->bSkipDuplicateMessages )
+ {
+ if (pMsgBufferDesc->pszLastMsg == EC_NULL )
+ {
+ /* first message */
+ pMsgBufferDesc->pszLastMsg = pCurrMsg->szMsgBuffer;
+ }
+ else if (OsStrncmp(pMsgBufferDesc->pszLastMsg, pCurrMsg->szMsgBuffer, pMsgBufferDesc->dwMsgSize) == 0 )
+ {
+ /* same message as before, just increment duplicate pointer */
+ pMsgBufferDesc->dwNumDuplicates++;
+ bSkipDuplicate = EC_TRUE;;
+ }
+ else
+ {
+ /* new message */
+ dwNumDuplicatesBeforeNewMsg = pMsgBufferDesc->dwNumDuplicates;
+ pMsgBufferDesc->dwNumDuplicates = 0;
+ pMsgBufferDesc->pszLastMsg = pCurrMsg->szMsgBuffer;
+ if (dwNumDuplicatesBeforeNewMsg>0 && pMsgBufferDesc->pszLastMsg[0]=='\0')
+ {
+ /* ignore empty duplicates... */
+ dwNumDuplicatesBeforeNewMsg = 0;
+ }
+ }
+ }
+ if (!bSkipDuplicate) dwNumMsgLeft--;
+
+ if (pMsgBufferDesc->bPrintConsole && !bSkipDuplicate)
+ {
+#if !(defined NOPRINTF)
+ /* print skip messages */
+ if (dwNumDuplicatesBeforeNewMsg > 0)
+ {
+ if (pMsgBufferDesc->bPrintTimestamp)
+ {
+ OsPrintf("%06d : ", (EC_T_INT)pCurrMsg->dwMsgTimestamp);
+ }
+ OsPrintf( "%d identical messages skipped\n", dwNumDuplicatesBeforeNewMsg);
+ }
+ /* print timestamp */
+ if ((pMsgBufferDesc->bPrintTimestamp) && (pMsgBufferDesc->bNewLine))
+ {
+ OsPrintf("%06d : ", (EC_T_INT)pCurrMsg->dwMsgTimestamp);
+ }
+ /* print message */
+ if (pCurrMsg->bMsgCrLf)
+ {
+ /* e.g. RTX64 requires terminating new-line directly appended to the message */
+ OsPrintf("%s\n", pCurrMsg->szMsgBuffer);
+ }
+ else
+ {
+ OsPrintf("%s", pCurrMsg->szMsgBuffer);
+ }
+#endif
+ }
+
+#if !(defined __RCX__) && !(defined __MET__) && !(defined RTAI)
+ if (pMsgBufferDesc->pbyLogMemory != EC_NULL )
+ {
+ if (!pMsgBufferDesc->bLogBufferFull && !bSkipDuplicate)
+ {
+ EC_T_DWORD dwWritten = 0;
+
+ /* print skip messages */
+ if (dwNumDuplicatesBeforeNewMsg > 0 )
+ {
+ if (pMsgBufferDesc->bPrintTimestamp)
+ {
+ dwWritten = dwWritten + OsSnprintf((EC_T_CHAR*)(pMsgBufferDesc->pbyNextLogMsg + dwWritten), MAX_MESSAGE_SIZE - dwWritten - 1, "%06d : ", (EC_T_INT) pCurrMsg->dwMsgTimestamp);
+ }
+ dwWritten = dwWritten + OsSnprintf((EC_T_CHAR*)(pMsgBufferDesc->pbyNextLogMsg + dwWritten), MAX_MESSAGE_SIZE - dwWritten - 1, "%d identical messages skipped\n", dwNumDuplicatesBeforeNewMsg );
+ SelectNextLogMemBuffer(pMsgBufferDesc);
+ }
+ if (!pMsgBufferDesc->bLogBufferFull)
+ {
+ dwWritten = 0;
+
+ /* memory logging */
+ if ((pMsgBufferDesc->bPrintTimestamp) && (pMsgBufferDesc->bNewLine))
+ {
+ dwWritten = dwWritten + OsSnprintf((EC_T_CHAR*)pMsgBufferDesc->pbyNextLogMsg + dwWritten, MAX_MESSAGE_SIZE - dwWritten - 1, "%06d : ", (EC_T_INT)pCurrMsg->dwMsgTimestamp);
+ }
+ /* print message */
+ dwWritten = dwWritten + OsSnprintf((EC_T_CHAR*)(pMsgBufferDesc->pbyNextLogMsg + dwWritten), MAX_MESSAGE_SIZE - dwWritten - 1, "%s", pCurrMsg->szMsgBuffer);
+
+ /* add new line */
+ if (pCurrMsg->bMsgCrLf)
+ {
+ OsSnprintf((EC_T_CHAR*)(pMsgBufferDesc->pbyNextLogMsg + dwWritten), MAX_MESSAGE_SIZE - dwWritten - 1, "%s", "\n");
+ }
+ SelectNextLogMemBuffer(pMsgBufferDesc);
+ }
+ }
+ }
+ else if (EC_NULL != pFileHandle)
+ {
+ /* don't use fprintf, some platforms don't support it! */
+
+ if (!bSkipDuplicate)
+ {
+ /* print skipped messages */
+ if (dwNumDuplicatesBeforeNewMsg > 0)
+ {
+ if (pMsgBufferDesc->bPrintTimestamp)
+ {
+ OsSnprintf(m_pchTempbuffer, 2*MAX_MESSAGE_SIZE - 1, "%06d : ", (EC_T_INT) pCurrMsg->dwMsgTimestamp);
+ OsFwrite(m_pchTempbuffer, OsStrlen(m_pchTempbuffer), 1, pFileHandle);
+ }
+ OsSnprintf(m_pchTempbuffer, 2*MAX_MESSAGE_SIZE - 1, "%d identical messages skipped\n", dwNumDuplicatesBeforeNewMsg);
+ OsFwrite(m_pchTempbuffer, OsStrlen(m_pchTempbuffer), 1, pFileHandle);
+ }
+ /* now fprintf, OsFflush, OsFclose etc. */
+ if ((pMsgBufferDesc->bPrintTimestamp) && (pMsgBufferDesc->bNewLine))
+ {
+ OsSnprintf(m_pchTempbuffer, 2*MAX_MESSAGE_SIZE - 1, "%06d : ", (EC_T_INT) pCurrMsg->dwMsgTimestamp);
+ OsFwrite(m_pchTempbuffer, OsStrlen(m_pchTempbuffer), 1, pFileHandle);
+ }
+ /* print message */
+ OsSnprintf(m_pchTempbuffer, 2*MAX_MESSAGE_SIZE - 1, "%s", pCurrMsg->szMsgBuffer);
+ OsFwrite(m_pchTempbuffer, OsStrlen(m_pchTempbuffer), 1, pFileHandle);
+
+ /* add new line */
+ if (pCurrMsg->bMsgCrLf)
+ {
+ OsSnprintf(m_pchTempbuffer, 2*MAX_MESSAGE_SIZE - 1, "\n");
+ OsFwrite(m_pchTempbuffer, OsStrlen(m_pchTempbuffer), 1, pFileHandle);
+ }
+ OsFflush(pFileHandle);
+ }
+ }
+#endif
+ /* check for new line */
+ pMsgBufferDesc->bNewLine = EC_FALSE;
+ if (pCurrMsg->bOsDbgMsg)
+ {
+ /* currently all messages generated within master stack contain '\n' */
+ /* check for CrLf in message */
+ if (*((EC_T_CHAR*)(pCurrMsg->szMsgBuffer + pCurrMsg->dwLen - 1)) == '\n')
+ {
+ pMsgBufferDesc->bNewLine = EC_TRUE;
+ }
+ }
+ else
+ {
+ if (pCurrMsg->bMsgCrLf)
+ {
+ pMsgBufferDesc->bNewLine = EC_TRUE;
+ }
+ }
+ pCurrMsg->bValid = EC_FALSE;
+ OsMemoryBarrier();
+ dwNewNextPrint = pMsgBufferDesc->dwNextPrintMsgIndex + 1;
+ if (dwNewNextPrint >= pMsgBufferDesc->dwNumMsgs )
+ {
+ dwNewNextPrint = 0;
+ }
+ pMsgBufferDesc->dwNextPrintMsgIndex = dwNewNextPrint;
+
+#if !(defined __RCX__) && !(defined __MET__) && !(defined RTAI)
+ if (bRollOver)
+ {
+ /* do roll over */
+ OsFclose(pFileHandle);
+
+ pFileHandle = OsFopen( szfileNameTemp, "w+" );
+ if (pFileHandle == EC_NULL )
+ {
+#if !(defined NOPRINTF)
+ OsPrintf( "ERROR: cannot create EtherCAT log file %s\n", szfileNameTemp );
+#endif
+ OsSleep( 3000 );
+
+ pMsgBufferDesc->pfMsgFile = pFileHandle;
+ }
+ else
+ {
+ pMsgBufferDesc->pfMsgFile = pFileHandle;
+ }
+
+ bRollOver = EC_FALSE;
+ }
+#endif
+ }
+ }
+ if (bLocked )
+ OsUnlock(m_poProcessMsgLock);
+
+ return;
+}
+
+
+/********************************************************************************/
+/** \brief Turn on/off OsDbgMsg hook printout
+*
+* \return N/A
+*/
+EC_T_BOOL CAtEmLogging::OsDbgMsgHookEnable(EC_T_BOOL bEnable)
+{
+ return m_bDbgMsgHookEnable = bEnable;
+}
+
+
+/********************************************************************************/
+/** \brief Hook for OsDbgMsg function
+*
+* NOTE: in real-time operation this function should return EC_FALSE to eliminate
+* an impact to the system behavior.
+* Here we store those messages into memory first and print them at a
+* later time from a lower priority thread for debugging purposes.
+*
+* \return EC_TRUE if OsDbgMsg() shall print the message, EC_FALSE if not
+*/
+EC_T_BOOL CAtEmLogging::OsDbgMsgHookWrapper(const EC_T_CHAR* szFormat, EC_T_VALIST vaArgs)
+{
+EC_T_BOOL bPrint = EC_TRUE;
+
+ if (EC_NULL != G_pOsDbgMsgLoggingInst)
+ {
+ bPrint = G_pOsDbgMsgLoggingInst->OsDbgMsgHook(szFormat, vaArgs);
+ }
+ if (bPrint)
+ {
+ OsVprintf(szFormat, vaArgs);
+ }
+ return EC_FALSE;
+}
+
+EC_T_BOOL CAtEmLogging::OsDbgMsgHook(const EC_T_CHAR* szFormat, EC_T_VALIST vaArgs)
+{
+EC_T_BOOL bPrint;
+
+ bPrint = !m_bDbgMsgHookEnable; // print messages outside as long as hook is not enabled
+ if (m_bDbgMsgHookEnable)
+ {
+ if (m_pAllMsgBufferDesc != EC_NULL )
+ {
+ if (m_pAllMsgBufferDesc->bIsInitialized )
+ {
+ InsertNewMsg( m_pAllMsgBufferDesc, szFormat, vaArgs, EC_FALSE, EC_TRUE );
+ }
+ else
+ {
+ bPrint = EC_TRUE;
+ }
+ }
+ else
+ {
+ bPrint = EC_TRUE;
+ }
+/*
+ else
+ {
+ EC_T_CHAR szMsg[256];
+
+ OsVsnprintf(szMsg, 256, szFormat, vaArgs);
+#ifdef VXWORKS
+ logMsg( "%s", (int)szMsg, 2,3,4,5,6 );
+#else
+#if !(defined NOPRINTF)
+ OsPrintf( "%s", szMsg );
+#endif
+#endif
+ }
+*/
+ }
+ return bPrint;
+}
+
+/********************************************************************************/
+/** \brief application error message function
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::LogError(const EC_T_CHAR* szFormat, ...)
+{
+EC_T_VALIST vaArgs;
+EC_T_DWORD dwRes = EC_E_NOERROR;
+
+
+ EC_VASTART(vaArgs, szFormat);
+ dwRes = InsertNewMsg(m_pAllMsgBufferDesc, szFormat, vaArgs);
+
+ /* important note: on VxWorks 6.1 PowerPC: re-using vaArgs in the next function call may fail without calling EC_VAEND/EC_VASTART!! */
+ EC_VAEND(vaArgs);
+ EC_VASTART(vaArgs, szFormat);
+
+ dwRes = InsertNewMsg( m_pErrorMsgBufferDesc, szFormat, vaArgs);
+ EC_VAEND(vaArgs);
+
+ return dwRes;
+}
+
+/********************************************************************************/
+/** \brief application error message function
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::LogErrorAdd(const EC_T_CHAR* szFormat, ...)
+{
+EC_T_VALIST vaArgs;
+EC_T_DWORD dwRes = EC_E_NOERROR;
+
+ EC_VASTART(vaArgs, szFormat);
+ dwRes = InsertNewMsg( m_pAllMsgBufferDesc, szFormat, vaArgs, EC_FALSE);
+
+ /* important note: on VxWorks 6.1 PowerPC: re-using vaArgs in the next function call may fail without calling EC_VAEND/EC_VASTART!! */
+ EC_VAEND(vaArgs);
+ EC_VASTART(vaArgs, szFormat);
+
+ dwRes = InsertNewMsg( m_pErrorMsgBufferDesc, szFormat, vaArgs, EC_FALSE);
+ EC_VAEND(vaArgs);
+ return dwRes;
+}
+
+/********************************************************************************/
+/** \brief application error message function
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::LogMsg(const EC_T_CHAR* szFormat, ...)
+{
+EC_T_VALIST vaArgs;
+EC_T_DWORD dwRes = EC_E_NOERROR;
+
+ EC_VASTART(vaArgs, szFormat);
+ dwRes = InsertNewMsg(m_pAllMsgBufferDesc, szFormat, vaArgs);
+ EC_VAEND(vaArgs);
+ return dwRes;
+}
+
+/********************************************************************************/
+/** \brief application error message function
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::LogMsgAdd(const EC_T_CHAR* szFormat, ...)
+{
+EC_T_VALIST vaArgs;
+EC_T_DWORD dwRes = EC_E_NOERROR;
+
+ EC_VASTART(vaArgs, szFormat);
+ dwRes = InsertNewMsg(m_pAllMsgBufferDesc, szFormat, vaArgs, EC_FALSE);
+ EC_VAEND(vaArgs);
+ return dwRes;
+}
+
+/********************************************************************************/
+/** \brief application DCM message function
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::LogDcm(const EC_T_CHAR* szFormat, ...)
+{
+EC_T_VALIST vaArgs;
+EC_T_DWORD dwRes = EC_E_NOERROR;
+
+ EC_VASTART(vaArgs, szFormat);
+#ifdef RTAI
+ static EC_T_DWORD dwLogDcmMsgCount = 0;
+ if ((dwLogDcmMsgCount % 100) == 0)
+ {
+ OsDbgMsgHookWrapper(szFormat, vaArgs);
+ OsDbgMsg("\n");
+ dwLogDcmMsgCount = 0;
+ }
+ dwLogDcmMsgCount++;
+#else
+ dwRes = InsertNewMsg(m_pDcmMsgBufferDesc, szFormat, vaArgs);
+#endif
+ EC_VAEND(vaArgs);
+ return dwRes;
+}
+
+/********************************************************************************/
+/** \brief application DCM message function
+*
+* \return N/A
+*/
+EC_T_DWORD CAtEmLogging::LogDcmAdd(const EC_T_CHAR* szFormat, ...)
+{
+EC_T_VALIST vaArgs;
+EC_T_DWORD dwRes = EC_E_NOERROR;
+
+ EC_VASTART(vaArgs, szFormat);
+ dwRes = InsertNewMsg(m_pDcmMsgBufferDesc, szFormat, vaArgs, EC_FALSE);
+ EC_VAEND(vaArgs);
+ return dwRes;
+}
+
+/********************************************************************************/
+/** \brief set log thread affinity
+*
+* \return N/A
+*/
+EC_T_BOOL CAtEmLogging::SetLogThreadAffinity(EC_T_DWORD dwCpuIndex)
+{
+EC_T_CPUSET CpuSet;
+EC_T_BOOL bOk = EC_TRUE;
+EC_UNREFPARM(dwCpuIndex);
+
+ if (m_pvLogThreadObj != EC_NULL)
+ {
+ EC_CPUSET_ZERO(CpuSet);
+ EC_CPUSET_SET(CpuSet, dwCpuIndex);
+ bOk = OsSetThreadAffinity(m_pvLogThreadObj, CpuSet);
+ }
+ return bOk;
+}
+
+/********************************************************************************/
+/** \brief set log directory
+*
+* \return EC_E_NOERROR or EC_E_NOMEMORY if szLogDir too long
+*/
+EC_T_DWORD CAtEmLogging::SetLogDir(EC_T_CHAR* szLogDir)
+{
+ if (OsStrlen(szLogDir) >= MAX_PATH_LEN)
+ {
+ return EC_E_NOMEMORY;
+ }
+ OsStrncpy(m_pchLogDir, szLogDir, OsStrlen(szLogDir) + 1);
+ return EC_E_NOERROR;
+}
+
+/*-END OF SOURCE FILE--------------------------------------------------------*/
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/Logging.h b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/Logging.h
--- /dev/null
@@ -0,0 +1,215 @@
+/*-----------------------------------------------------------------------------
+ * Logging.h
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description EtherCAT Master application logging header
+ *---------------------------------------------------------------------------*/
+
+#ifndef __LOGGING_H__
+#define __LOGGING_H__ 1
+
+/*-INCLUDES------------------------------------------------------------------*/
+#if (defined __MET__)
+#include "fio.h"
+#else
+#include "stdio.h"
+#endif
+
+#ifndef INC_ECOS
+#include "EcOs.h"
+#endif
+#ifndef INC_ECTIMER
+#include "EcTimer.h"
+#endif
+
+/*-MACROS--------------------------------------------------------------------*/
+
+
+/*-DEFINES-------------------------------------------------------------------*/
+
+/* log thread priority (very low) */
+#if defined WIN32 && !defined UNDER_CE && !defined RTOS_32
+ #define LOG_ROLLOVER ((EC_T_WORD)0)
+#elif (defined __RCX__)
+ #define LOG_ROLLOVER ((EC_T_WORD)0)
+#elif (defined RTOS_32)
+ #define LOG_ROLLOVER ((EC_T_WORD)3000)
+#else
+ #define LOG_ROLLOVER ((EC_T_WORD)10000)
+#endif
+
+#define MAX_PATH_LEN 256
+
+/*-GLOBAL VARIABLES-----------------------------------------------------------*/
+
+extern EC_T_BOOL bLogFileEnb;
+
+/*-TYPEDEFS------------------------------------------------------------------*/
+
+typedef struct _LOG_MSG_DESC
+{
+ EC_T_BOOL bValid; /* entry is valid */
+ EC_T_CHAR* szMsgBuffer; /* buffers */
+ EC_T_DWORD dwLen; /* message size */
+ EC_T_DWORD dwMsgTimestamp; /* timestamp values */
+ EC_T_DWORD dwMsgThreadId; /* threadId values */
+ EC_T_BOOL bMsgCrLf; /* CR/LF do/don't */
+ EC_T_BOOL bOsDbgMsg; /* OsDbgMsg values */
+} LOG_MSG_DESC;
+
+
+
+typedef struct _MSG_BUFFER_DESC
+{
+ struct _MSG_BUFFER_DESC* pNextMsgBuf; /* link to next message buffer */
+ LOG_MSG_DESC* paMsg; /* array of messages */
+ EC_T_DWORD dwMsgSize; /* message size */
+ EC_T_DWORD dwNumMsgs; /* number of messages */
+ EC_T_DWORD dwNextEmptyMsgIndex; /* index of next empty message buffer */
+ EC_T_DWORD dwNextPrintMsgIndex; /* index of next message buffer to print */
+ EC_T_CHAR szMsgLogFileName[MAX_PATH_LEN]; /* message log file name */
+ EC_T_CHAR szMsgLogFileExt[4]; /* message log file extension */
+ FILE* pfMsgFile; /* file pointer for message log file */
+ EC_T_BOOL bPrintTimestamp; /* EC_TRUE if a timestamp shall be printed in the log file */
+ EC_T_BOOL bPrintConsole; /* EC_TRUE if the message shall be printed on the console */
+ EC_T_BOOL bIsInitialized; /* EC_TRUE if message buffer is initialized */
+ EC_T_WORD wLogFileIndex; /* Index of current log file */
+ EC_T_WORD wEntryCounter; /* Entries to detect roll over */
+ EC_T_WORD wEntryCounterLimit; /* Entries before roll over */
+ EC_T_WORD wRes;
+ /* logging into memory buffer */
+ EC_T_CHAR szLogName[MAX_PATH_LEN];/* name of the logging buffer */
+ EC_T_BYTE* pbyLogMemory; /* if != EC_NULL then log into memory instead of file */
+ EC_T_BYTE* pbyNextLogMsg; /* pointer to next logging message */
+ EC_T_DWORD dwLogMemorySize; /* size of logging memory */
+ EC_T_BOOL bLogBufferFull; /* EC_TRUE if log buffer is full */
+ /* skip identical messages */
+ EC_T_BOOL bSkipDuplicateMessages; /* if set to EC_TRUE, then multiple identical messages will not be printed out */
+ EC_T_DWORD dwNumDuplicates; /* if 0, the new message is not duplicated */
+ EC_T_CHAR* pszLastMsg; /* pointer to last message (points into message buffer) */
+ EC_T_BOOL bNewLine; /* EC_TRUE if last message printed with CrLf */
+} MSG_BUFFER_DESC;
+
+
+
+/*-FORWARD DECLARATIONS------------------------------------------------------*/
+
+
+/*-CLASS---------------------------------------------------------------------*/
+
+class CAtEmLogging
+{
+
+public:
+ CAtEmLogging( EC_T_VOID );
+
+ EC_T_BOOL OsDbgMsgHook( const
+ EC_T_CHAR* szFormat,
+ EC_T_VALIST vaArgs );
+ EC_T_DWORD LogMsg( const
+ EC_T_CHAR* szFormat,... );
+ EC_T_DWORD LogMsgAdd( const
+ EC_T_CHAR* szFormat,... );
+ EC_T_DWORD LogError( const
+ EC_T_CHAR* szFormat,... );
+ EC_T_DWORD LogErrorAdd( const
+ EC_T_CHAR* szFormat,... );
+ EC_T_DWORD LogDcm( const
+ EC_T_CHAR* szFormat,... );
+ EC_T_DWORD LogDcmAdd( const
+ EC_T_CHAR* szFormat,... );
+ EC_T_VOID InitLogging( EC_T_DWORD dwMasterID,
+ EC_T_WORD wRollOver,
+ EC_T_DWORD dwPrio,
+ EC_T_DWORD dwCpuIndex,
+ EC_T_CHAR* szFilenamePrefix = EC_NULL,
+ EC_T_DWORD dwStackSize = 0x4000 );
+ EC_T_VOID SetLogMsgBuf( EC_T_BYTE* pbyLogMem,
+ EC_T_DWORD dwSize );
+ EC_T_VOID SetLogErrBuf( EC_T_BYTE* pbyLogMem,
+ EC_T_DWORD dwSize );
+ EC_T_VOID SetLogDcmBuf( EC_T_BYTE* pbyLogMem,
+ EC_T_DWORD dwSize );
+ EC_T_VOID DeinitLogging( EC_T_VOID );
+ EC_T_BOOL SetLogThreadAffinity( EC_T_DWORD dwCpuIndex );
+ EC_T_BOOL OsDbgMsgHookEnable( EC_T_BOOL bEnable );
+
+ static
+ EC_T_BOOL OsDbgMsgHookWrapper( const
+ EC_T_CHAR* szFormat,
+ EC_T_VALIST vaArgs );
+ EC_T_VOID tAtEmLog( EC_T_VOID* pvParms );
+ EC_T_VOID ProcessAllMsgs( EC_T_VOID );
+
+ struct _MSG_BUFFER_DESC* AddLogBuffer( EC_T_DWORD dwMasterID,
+ EC_T_WORD wRollOver,
+ EC_T_DWORD dwBufferSize,
+ EC_T_BOOL bSkipDuplicates,
+ EC_T_CHAR* szLogName,
+ EC_T_CHAR* szLogFilename,
+ EC_T_CHAR* szLogFileExt,
+ EC_T_BOOL bPrintConsole,
+ EC_T_BOOL bPrintTimestamp );
+
+ static
+ EC_T_VOID SetMsgBuf( MSG_BUFFER_DESC* pMsgBufferDesc,
+ EC_T_BYTE* pbyLogMem,
+ EC_T_DWORD dwSize );
+
+ EC_T_DWORD InsertNewMsg( MSG_BUFFER_DESC* pMsgBufferDesc,
+ const
+ EC_T_CHAR* szFormat,
+ EC_T_VALIST vaArgs,
+ EC_T_BOOL bDoCrLf=EC_TRUE,
+ EC_T_BOOL bOsDbgMsg=EC_FALSE );
+
+ EC_T_DWORD SetLogDir( EC_T_CHAR* szLogDir );
+
+
+private:
+ static
+ EC_T_BOOL InitMsgBuffer( MSG_BUFFER_DESC* pMsgBufferDesc,
+ EC_T_DWORD dwMsgSize,
+ EC_T_DWORD dwNumMsgs,
+ EC_T_BOOL bSkipDuplicates,
+ EC_T_BOOL bPrintConsole,
+ EC_T_BOOL bPrintTimestamp,
+ EC_T_CHAR* szMsgLogFileName,
+ EC_T_CHAR* szMsgLogFileExt,
+ EC_T_WORD wRollOver,
+ EC_T_CHAR* szLogName );
+
+ EC_T_VOID DeinitMsgBuffer( MSG_BUFFER_DESC* pMsgBufferDesc );
+ EC_T_VOID ProcessMsgs( MSG_BUFFER_DESC* pMsgBufferDesc );
+
+ static
+ EC_T_VOID SelectNextLogMemBuffer( MSG_BUFFER_DESC* pMsgBufferDesc );
+
+ static
+ EC_T_VOID tAtEmLogWrapper( EC_T_VOID* pvParms );
+
+ EC_T_PVOID m_pvLogThreadObj;
+ EC_T_BOOL m_bLogTaskRunning;
+ EC_T_BOOL m_bShutdownLogTask;
+
+ MSG_BUFFER_DESC* m_pFirstMsgBufferDesc; /* pointer to first message buffer */
+ MSG_BUFFER_DESC* m_pLastMsgBufferDesc; /* link to last message buffer */
+ MSG_BUFFER_DESC* m_pAllMsgBufferDesc; /* buffer for all messages */
+ MSG_BUFFER_DESC* m_pErrorMsgBufferDesc; /* buffer for application error messages */
+ MSG_BUFFER_DESC* m_pDcmMsgBufferDesc; /* DCM buffer */
+ EC_T_CHAR* m_pchTempbuffer;
+ EC_T_VOID* m_poInsertMsgLock; /* lock object for inserting new messages */
+ EC_T_VOID* m_poProcessMsgLock; /* lock object for processing messages */
+ EC_T_BOOL m_bDbgMsgHookEnable;
+
+ CEcTimer m_oMsgTimeout;
+ CEcTimer m_oSettlingTimeout;
+ EC_T_DWORD m_dwNumMsgsSinceMsrmt;
+ EC_T_BOOL m_bSettling;
+
+ EC_T_CHAR m_pchLogDir[MAX_PATH_LEN]; /* directory for all EtherCAT logging files */
+};
+
+#endif /*__LOGGING_H__*/
+
+/*-END OF SOURCE FILE--------------------------------------------------------*/
diff --git a/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/SlaveInfo.h b/EC_Master_SysBios_Am572x_20170214/Examples/EcMasterDemo/SlaveInfo.h
--- /dev/null
@@ -0,0 +1,549 @@
+/*-----------------------------------------------------------------------------
+ * SlaveInfo.h
+ * Copyright acontis technologies GmbH, Weingarten, Germany
+ * Response Stefan Zintgraf
+ * Description Slave Info header
+ *---------------------------------------------------------------------------*/
+
+#ifndef INC_SLAVEINFO
+#define INC_SLAVEINFO 1
+
+/*-TYPEDEFS------------------------------------------------------------------*/
+typedef enum _T_eEtherCAT_Vendor
+{
+ ecvendor_etg = 0x00000001,
+ ecvendor_beckhoff = 0x00000002,
+ ecvendor_scuola_superiore_s_anna = 0x00000003,
+ ecvendor_ixxat = 0x00000004,
+ ecvendor_vector_informatik = 0x00000005,
+ ecvendor_knestel = 0x00000006,
+ ecvendor_cmz_sistemi = 0x0000000a,
+ ecvendor_softing = 0x0000000d,
+ ecvendor_microcontrol = 0x0000000e,
+ ecvendor_pollmeier = 0x0000000f,
+ ecvendor_lust = 0x00000010,
+ ecvendor_kuebler = 0x00000013,
+ ecvendor_keb = 0x00000014,
+ ecvendor_lti = 0x00000016,
+ ecvendor_esd_electronic_design = 0x00000017,
+ ecvendor_hms_industrial_networks = 0x0000001b,
+ ecvendor_epis_automation = 0x0000001c,
+ ecvendor_festo = 0x0000001D,
+ ecvendor_wago = 0x00000021,
+ ecvendor_boschrexroth = 0x00000024,
+ ecvendor_moog = 0x00000028,
+ ecvendor_port = 0x00000034,
+ ecvendor_buerkert_werke = 0x00000039,
+ ecvendor_lenze = 0x0000003B,
+ ecvendor_tigris_electronic = 0x00000042,
+ ecvendor_hilscher = 0x00000044,
+ ecvendor_murrelektronik = 0x0000004F,
+ ecvendor_bombardier_transportation = 0x00000051,
+ ecvendor_komax = 0x00000057,
+ ecvendor_sew_eurodrive = 0x00000059,
+ ecvendor_bachmann_electronic = 0x00000062,
+ ecvendor_danaher = 0x0000006A,
+ ecvendor_kollmorgen = 0xE000006A,
+ ecvendor_woodward_seg = 0x0000006b,
+ ecvendor_bernecker_rainer_ie = 0x0000006c,
+ ecvendor_infranor_electronics = 0x00000082,
+ ecvendor_omron = 0x00000083,
+ ecvendor_gefran = 0x00000093,
+ ecvendor_elmo_motion = 0x0000009a,
+ ecvendor_sontheim_industrie_elektronik = 0x000000a0,
+ ecvendor_hirschmann_automation = 0x000000a5,
+ ecvendor_copley = 0x000000AB,
+ ecvendor_pepperl_fuchs = 0x000000ad,
+ ecvendor_johannes_huebner = 0x000000af,
+ ecvendor_abb_oy_drives = 0x000000b7,
+ ecvendor_stoeber = 0x000000b9,
+ ecvendor_messung_systems = 0x000000ce,
+ ecvendor_bonfiglioli_vectron = 0x000000d5,
+ ecvendor_phase_motion_control = 0x000000d9,
+ ecvendor_metronix = 0x000000e4,
+ ecvendor_ascon = 0x000000e9,
+ ecvendor_controltechniques = 0x000000F9,
+ ecvendor_maxon_motor = 0x000000FB,
+ ecvendor_keba = 0x00000105,
+ ecvendor_wittenstein = 0x0000010a,
+ ecvendor_twk_elektronik = 0x0000010d,
+ ecvendor_psa_elettronica = 0x0000010f,
+ ecvendor_smc = 0x00000114,
+ ecvendor_jvl_industri_elektronik = 0x00000117,
+ ecvendor_hottinger_baldwin = 0x0000011d,
+ ecvendor_leuze_electronic = 0x00000121,
+ ecvendor_jumo = 0x00000126,
+ ecvendor_hsd = 0x00000129,
+ ecvendor_lika_electronic = 0x0000012e,
+ ecvendor_csm = 0x0000012f,
+ ecvendor_lpkf_motion_control = 0x00000146,
+ ecvendor_imc_messysteme = 0x0000014a,
+ ecvendor_baumueller = 0x0000015A,
+ ecvendor_pneumax = 0x0000017a,
+ ecvendor_promess = 0x00000190,
+ ecvendor_deutschmann = 0x0000019d,
+ ecvendor_golden = 0x0000019e,
+ ecvendor_brunner_elektronik = 0x000001a1,
+ ecvendor_technosoft = 0x000001a3,
+ ecvendor_peyer_engineering = 0x000001b4,
+ ecvendor_robox = 0x000001B5,
+ ecvendor_parker = 0xE00001B5,
+ ecvendor_sanyo_denki = 0x000001b9,
+ ecvendor_delta_electronics = 0x000001dd,
+ ecvendor_amk = 0x000001eb,
+ ecvendor_national_instruments = 0x000001F9,
+ ecvendor_fernsteuergeraete_kurt_oelsch = 0x000001fc,
+ ecvendor_idam = 0x000001FD,
+ ecvendor_prueftechnik_ndt = 0x000001fe,
+ ecvendor_baumer_th = 0x00000204,
+ ecvendor_esitron_electronic = 0x00000207,
+ ecvendor_systeme_helmholz = 0x00000223,
+ ecvendor_pantec = 0x00000225,
+ ecvendor_abb_stotz_kontakt = 0x0000023a,
+ ecvendor_berghof_automationstechnik = 0x0000023b,
+ ecvendor_stotz_feinmesstechnik = 0x0000024f,
+ ecvendor_dunkermotoren = 0x00000257,
+ ecvendor_roche_diagnostics = 0x00000283,
+ ecvendor_toshiba_schneider = 0x00000284,
+ ecvendor_bihl_wiedemann = 0x00000285,
+ ecvendor_trinamic_motion_control = 0x00000286,
+ ecvendor_performance_motion_devices = 0x00000296,
+ ecvendor_ingenia_cat = 0x0000029c,
+ ecvendor_crevis = 0x0000029d,
+ ecvendor_thk = 0x000002d0,
+ ecvendor_digitronic = 0x00000302,
+ ecvendor_infineon_technologies = 0x0000034E,
+ ecvendor_hanyang = 0x000003ae,
+ ecvendor_baldor_uk = 0x000003db,
+ ecvendor_beck_ipc = 0x00000501,
+ ecvendor_etas = 0x00000502,
+ ecvendor_phytec_messtechnik = 0x00000504,
+ ecvendor_anca_motion = 0x00000505,
+ ecvendor_fh_koeln = 0x00000506,
+ ecvendor_nuvation_research = 0x00000508,
+ ecvendor_tr = 0x00000509,
+ ecvendor_gantner = 0x0000050a,
+ ecvendor_mks_systems = 0x0000050b,
+ ecvendor_abb_robotics = 0x0000050c,
+ ecvendor_unitro_fleischmann = 0x0000050d,
+ ecvendor_zub_machine_control = 0x0000050e,
+ ecvendor_dspace = 0x0000050f,
+ ecvendor_samsung = 0x00000511,
+ ecvendor_bce = 0x00000512,
+ ecvendor_jaeger_messtechnik = 0x00000513,
+ ecvendor_tetra = 0x00000514,
+ ecvendor_justek = 0x00000515,
+ ecvendor_baumer_thalheim = 0x00000516,
+ ecvendor_elin_ebg_traction = 0x00000517,
+ ecvendor_meka_robotics = 0x00000518,
+ ecvendor_altera_japan = 0x00000519,
+ ecvendor_ebv_elektronik = 0x0000051a,
+ ecvendor_igh = 0x0000051b,
+ ecvendor_iav = 0x0000051c,
+ ecvendor_hitachi = 0x0000051d,
+ ecvendor_tenasys = 0x0000051e,
+ ecvendor_pondis = 0x0000051f,
+ ecvendor_moog_italiana = 0x00000520,
+ ecvendor_wallner_automation = 0x00000522,
+ ecvendor_avl_list = 0x00000523,
+ ecvendor_ritter_elektronik = 0x00000524,
+ ecvendor_zwick = 0x00000527,
+ ecvendor_dresdenelektronik = 0x00000528,
+ ecvendor_philips_healthcare = 0x0000052c,
+ ecvendor_chess = 0x0000052d,
+ ecvendor_nct = 0x0000052e,
+ ecvendor_anywire = 0x0000052f,
+ ecvendor_shadow_robot = 0x00000530,
+ ecvendor_fecon = 0x00000531,
+ ecvendor_fh_suedwestfahlen = 0x00000532,
+ ecvendor_add2 = 0x00000533,
+ ecvendor_arm_automation = 0x00000534,
+ ecvendor_knapp_logistik = 0x00000537,
+ ecvendor_getriebebau_nord = 0x00000538,
+ ecvendor_yaskawa = 0x00000539,
+ ecvendor_oki = 0x0000053a,
+ ecvendor_takasaki_kyoudou = 0x0000053b,
+ ecvendor_nittetsu_elex = 0x0000053c,
+ ecvendor_unjo = 0x0000053e,
+ ecvendor_eads_deutschland = 0x0000053f,
+ ecvendor_acs_motion_control = 0x00000540,
+ ecvendor_keyence = 0x00000541,
+ ecvendor_mefi = 0x00000542,
+ ecvendor_mut = 0x00000543,
+ ecvendor_isw_uni_stuttgart = 0x00000544,
+ ecvendor_elsena = 0x00000545,
+ ecvendor_be_semiconductor = 0x00000546,
+ ecvendor_hauni_lni = 0x00000547,
+ ecvendor_etel = 0x00000548,
+ ecvendor_vat_vakuumventile = 0x00000549,
+ ecvendor_laytec = 0x0000054a,
+ ecvendor_num = 0x0000054b,
+ ecvendor_hauni_maschinenbau = 0x0000054c,
+ ecvendor_exatronic = 0x0000054d,
+ ecvendor_iim_chinese_aos = 0x0000054e,
+ ecvendor_tu_eindhoven = 0x0000054f,
+ ecvendor_scansonic = 0x00000550,
+ ecvendor_shanghai_sodick_sw = 0x00000551,
+ ecvendor_chuo_electronics = 0x00000552,
+ ecvendor_agie = 0x00000553,
+ ecvendor_hei_canton_de_vaud = 0x00000555,
+ ecvendor_jenny_science = 0x00000557,
+ ecvendor_industrial_control_communications = 0x00000558,
+ ecvendor_ckd_elektrotechnika = 0x0000055a,
+ ecvendor_qem = 0x0000055b,
+ ecvendor_simatex = 0x0000055c,
+ ecvendor_kithara = 0x0000055d,
+ ecvendor_converteam = 0x0000055e,
+ ecvendor_ara = 0x0000055f,
+ ecvendor_tata_consultancy = 0x00000560,
+ ecvendor_tiab = 0x00000562,
+ ecvendor_rkc_instrument = 0x00000563,
+ ecvendor_switched_reluctance = 0x00000564,
+ ecvendor_avnet_electronics = 0x00000566,
+ ecvendor_abb_force_measurement = 0x00000567,
+ ecvendor_kunbus = 0x00000569,
+ ecvendor_acd_antriebstechnik = 0x0000056a,
+ ecvendor_bronkhorst = 0x0000056b,
+ ecvendor_k_mecs = 0x0000056c,
+ ecvendor_thomson_broadcast = 0x0000056d,
+ ecvendor_ufg_elettronica = 0x0000056e,
+ ecvendor_xilinx = 0x0000056f,
+ ecvendor_abb_power_systems = 0x00000570,
+ ecvendor_servoland = 0x00000571,
+ ecvendor_hivertec = 0x00000572,
+ ecvendor_fike_europe = 0x00000573,
+ ecvendor_ropex = 0x00000576,
+ ecvendor_tlu = 0x00000577,
+ ecvendor_prodrive = 0x00000579,
+ ecvendor_miho_inspektionssysteme = 0x0000057a,
+ ecvendor_tokyo_electron = 0x0000057b,
+ ecvendor_lintec = 0x0000057c,
+ ecvendor_simplex_vision = 0x0000057d,
+ ecvendor_sus = 0x00000581,
+ ecvendor_trsystems = 0x00000582,
+ ecvendor_harmonic_drive = 0x00000583,
+ ecvendor_staeubli_faverges = 0x00000584,
+ ecvendor_scienlab_electronic = 0x00000585,
+ ecvendor_fujisoft = 0x00000587,
+ ecvendor_iai_corporation = 0x00000588,
+ ecvendor_promavtomatika = 0x00000589,
+ ecvendor_kistler_instrumente = 0x0000058a,
+ ecvendor_lauda_wobser = 0x0000058b,
+ ecvendor_schweitzer_engineering_labs = 0x0000058c,
+ ecvendor_mutracx = 0x0000058e,
+ ecvendor_algo = 0x0000058f,
+ ecvendor_muehlbauer = 0x00000590,
+ ecvendor_sealevel_systems = 0x00000592,
+ ecvendor_igm_robotersysteme = 0x00000593,
+ ecvendor_zbe = 0x00000595,
+ ecvendor_schneider_electric = 0x00000596,
+ ecvendor_fraunhofer_iosb_ina = 0x00000597,
+ ecvendor_skf_magnetic_bearings = 0x00000598,
+ ecevndor_galil_motion_control = 0x00000599,
+ ecvendor_ihi = 0x0000059a,
+ ecvendor_wenglor_sensoric = 0x0000059b,
+ ecvendor_ingeteam = 0x0000059c,
+ ecvendor_texas_instruments = 0xe000059d,
+ ecvendor_micro_vu = 0x0000059e,
+ ecvendor_oehri_electronic = 0x0000059f,
+ ecvendor_nagano_oki = 0x00000600,
+ ecvendor_condalo = 0x00000601,
+ ecvendor_tg_drives = 0x00000666,
+ ecvendor_schleuniger = 0x0000066e,
+ ecvendor_koenig = 0x00000777,
+ ecvendor_shanghai_cnc = 0x00000900,
+ ecvendor_mitsubishi = 0x00000a1e,
+ ecvendor_john_deere = 0x00000d05,
+ ecvendor_cantops = 0x00001122,
+ ecvendor_ids = 0x000012ad,
+ ecvendor_adlink = 0x0000144a,
+ ecvendor_eubus = 0x0000147a,
+ ecvendor_unico = 0x00001502,
+ ecvendor_dlr = 0x00001616,
+ ecvendor_hei_canton_de_vaud_reds = 0x0000179a,
+ ecvendor_bystorm = 0x00001a21,
+ ecvendor_ipetronik = 0x00001a90,
+ ecvendor_sennheiser = 0x00001b66,
+ ecvendor_danieli_automation = 0x00002304,
+ ecvendor_acontis = 0x00004154,
+ ecvendor_kuka = 0x000060c8,
+ ecvendor_nat = 0x00006c78,
+ ecvendor_mecapion = 0x00007595,
+ ecvendor_ontec = 0x00007604,
+ ecvendor_foxnum = 0x00007715,
+ ecvendor_kyoei = 0x00007716,
+ ecvendor_brother = 0x00008562,
+ ecvendor_shenyang_machine_tool = 0x00008818,
+ ecvendor_soft_servo = 0x00009555,
+ ecvendor_vipa = 0x0000affe,
+ ecvendor_gd = 0x0000bebe,
+ ecvendor_keba_at = 0x0000ceba,
+ ecvendor_willow_garage = 0x0000eeee,
+ ecvendor_interroll = 0x0000fe09,
+ ecvendor_silica_avnet = 0x0000fedc,
+ ecvendor_altima = 0x00414c54,
+ ecvendor_kuhnke = 0x0048554B,
+ ecvendor_jat = 0x004A4154,
+ ecvendor_heidelberger = 0x004d4448,
+ ecvendor_mecalc = 0x004d4543,
+ ecvendor_samsung_sec = 0x00534543,
+ ecvendor_aixcon = 0x00616978,
+ ecvendor_kk_electronic = 0x00ae4b4b,
+ ecvendor_sick = 0x01000056,
+ ecvendor_parker_hannifin = 0x01000089,
+ ecvendor_balluf = 0x010000e8,
+ ecvendor_ma_vi = 0x01abcdef,
+ ecvendor_kraeutner_software = 0x01c0ffee,
+ ecvendor_parker_hannifin_eme = 0x02000089,
+ ecvendor_danfoss_drives = 0x0200008d,
+ ecvendor_parker_hannifin_eme_630 = 0x03000089,
+ ecvendor_parker_hannifin_ssd = 0x04000089,
+ ecvendor_schneider_motion_control = 0x0800005a,
+ ecvendor_fas = 0x0fa00000,
+ ecvendor_beckhoff_hardware = 0x10000002,
+ ecvendor_hengstler = 0x20041961,
+ ecvendor_lenord_bauer = 0x20422b4c,
+ ecvendor_ibv = 0x21494256,
+ ecvendor_red_one = 0x40524f54,
+ ecvendor_shf_communication = 0x46485320,
+ ecvendor_grossenbacher = 0x47535953,
+ ecvendor_nti_linmot = 0x4c4e5449,
+ ecvendor_eltromat = 0x4c746c65,
+ ecvendor_arte_motion = 0x65547241,
+ ecvendor_paul_maschinenfabrik = 0x7061756c,
+ ecvendor_handtmann = 0xdeadbeef,
+
+ /* Borland C++ datatype alignment correction */
+ ecvendor_BCppDummy = 0xFFFFFFFF
+} T_eEtherCAT_Vendor;
+
+typedef enum _T_eEtherCAT_ProductCode
+{
+ /* Beckhoff Automation */
+ ecprodcode_beck_AX2000_B110 = 0x07D06014,
+ ecprodcode_beck_AX2000_B120 = 0x07D06014,
+ ecprodcode_beck_BK1120 = 0x04602C22,
+ ecprodcode_beck_CX1100_0004 = 0x044C6032,
+ ecprodcode_beck_CU1128 = 0x04685432,
+ ecprodcode_beck_EK1100 = 0x044C2C52,
+ ecprodcode_beck_EK1101 = 0x044D2C52,
+ ecprodcode_beck_EK1122 = 0x04622C52,
+ ecprodcode_beck_EK1814 = 0x07162C52,
+ ecprodcode_beck_EK1818 = 0x071A2C52,
+ ecprodcode_beck_EK1828 = 0x07242C52,
+ ecprodcode_beck_EK1914 = 0x077A2C52,
+ ecprodcode_beck_EL1002 = 0x03EA3052,
+ ecprodcode_beck_EL1004 = 0x03EC3052,
+ ecprodcode_beck_EL1004_0010 = 0x03EC3052,
+ ecprodcode_beck_EL1008 = 0x03F03052,
+ ecprodcode_beck_EL1012 = 0x03F43052,
+ ecprodcode_beck_EL1014 = 0x03F63052,
+ ecprodcode_beck_EL1014_0010 = 0x03F63052,
+ ecprodcode_beck_EL1018 = 0x03FA3052,
+ ecprodcode_beck_EL1034 = 0x040A3052,
+ ecprodcode_beck_EL1094 = 0x04463052,
+ ecprodcode_beck_EL1114 = 0x045A3052,
+ ecprodcode_beck_EL1259 = 0x04EB3052,
+ ecprodcode_beck_EL1262 = 0x04EE3052,
+ ecprodcode_beck_EL1889 = 0x07613052,
+ ecprodcode_beck_EL1904 = 0x07703052,
+ ecprodcode_beck_EL2002 = 0x07D23052,
+ ecprodcode_beck_EL2004 = 0x07D43052,
+ ecprodcode_beck_EL2008 = 0x07D83052,
+ ecprodcode_beck_EL2032 = 0x07F03052,
+ ecprodcode_beck_EL2262 = 0x08D63052,
+ ecprodcode_beck_EL2502 = 0x09C63052,
+ ecprodcode_beck_EL2521 = 0x09D93052,
+ ecprodcode_beck_EL2521_1001 = 0x09D93052,
+ ecprodcode_beck_EL2809 = 0x0AF93052,
+ ecprodcode_beck_EL2889 = 0x0B493052,
+ ecprodcode_beck_EL2904 = 0x0B583052,
+ ecprodcode_beck_EL3064 = 0x0BF83052,
+ ecprodcode_beck_EL3102 = 0x0C1E3052,
+ ecprodcode_beck_EL3112 = 0x0C283052,
+ ecprodcode_beck_EL3122 = 0x0C323052,
+ ecprodcode_beck_EL3142 = 0x0C463052,
+ ecprodcode_beck_EL3142_0010 = 0x0C463052,
+ ecprodcode_beck_EL3152 = 0x0C503052,
+ ecprodcode_beck_EL3162 = 0x0C5A3052,
+ ecprodcode_beck_EL3202 = 0x0C823052,
+ ecprodcode_beck_EL3255 = 0x0CB73052,
+ ecprodcode_beck_EL3312 = 0x0CF03052,
+ ecprodcode_beck_EL3702 = 0x0E763052,
+ ecprodcode_beck_EL4002 = 0x0FA23052,
+ ecprodcode_beck_EL4004 = 0x0FA43052,
+ ecprodcode_beck_EL4102 = 0x10063052,
+ ecprodcode_beck_EL4112 = 0x10103052,
+ ecprodcode_beck_EL4112_0010 = 0x10103052,
+ ecprodcode_beck_EL4122 = 0x101A3052,
+ ecprodcode_beck_EL4132 = 0x10243052,
+ ecprodcode_beck_EL5001 = 0x13893052,
+ ecprodcode_beck_EL5101 = 0x13ED3052,
+ ecprodcode_beck_EL5151 = 0x141F3052,
+ ecprodcode_beck_EL5152 = 0x14203052,
+ ecprodcode_beck_AX5206 = 0x14566012,
+ ecprodcode_beck_EL6001 = 0x17713052,
+ ecprodcode_beck_EL6021 = 0x17853052,
+ ecprodcode_beck_EL6601 = 0x19C93052,
+ ecprodcode_beck_EL6614 = 0x19D63052,
+ ecprodcode_beck_EL6690 = 0x1A223052,
+ ecprodcode_beck_EL6692 = 0x1A243052,
+ ecprodcode_beck_EL6731 = 0x1A4B3052,
+ ecprodcode_beck_EL6731_0010 = 0x1A4B3052,
+ ecprodcode_beck_EL6751 = 0x1A5F3052,
+ ecprodcode_beck_EL6752 = 0x1A603052,
+ ecprodcode_beck_EL6900 = 0x1AF43052,
+ ecprodcode_beck_EL6930 = 0x1B123052,
+ ecprodcode_beck_EL9800 = 0x26483052,
+ ecprodcode_beck_FM5001 = 0x13893462,
+ ecprodcode_beck_EK1110 = 0x04562C52,
+ ecprodcode_beck_EL2252 = 0x08CC3052,
+ ecprodcode_beck_EL1252 = 0x04E43052,
+ ecprodcode_beck_EL9820 = 0x04570862,
+
+ /* Ixxat */
+ ecprodcode_ixx_iem = 0x00000001,
+ ecprodcode_ixx_ETCio100 = 0x00000006,
+
+ /* ESR Pollmeier */
+ ecprodcode_esr_Trio = 0x00001A63,
+ ecprodcode_esr_Midi = 0x00001A59,
+ ecprodcode_esr_Trio_1 = 0x67550000, /* may not work, ESR faulty Device Desc XML? */
+
+ /* KUEBLER */
+ ecprodcode_kuebler_Multiturn5868 = 0x5868B111,
+
+ /* KEB */
+ ecprodcode_keb_KEB1736F5_3d = 0x000006C8,
+ ecprodcode_keb_EcatGateway = 0x00002201,
+
+ /* MOOG */
+ ecprodcode_moog_anin = 0x00000001,
+ ecprodcode_moog_ServoValveD671 = 0x000000D5,
+
+ /* Lenze */
+ ecprodcode_ldc_el9400 = 0x00000001,
+ ecprodcode_ldc_e94aycet = 0x00000002,
+ ecprodcode_ldc_servogun2 = 0x00000052,
+ ecprodcode_ldc_servogun3 = 0x00000053,
+ ecprodcode_ldc_epms130 = 0x00000514,
+ ecprodcode_ldc_el8400 = 0x000CD156,
+ ecprodcode_ldc_stateline = 0x02010000,
+ ecprodcode_ldc_highlineCIA402 = 0x38079D3D,
+
+ /* Hilscher */
+ ecprodcode_hil_NXSB100 = 0x00000005,
+ ecprodcode_hil_NXSB100DC = 0x7874656E,
+
+ &nbs