Staging: add epl stack
This is the openPOWERLINK network stack from systec electronic.
It's a bit messed up as there is a driver mixed into the
middle of it, lots of work needs to be done to unwind the
different portions to make it sane.
Cc: Daniel Krueger <daniel.krueger@systec-electronic.com>
Cc: Ronald Sieber <Ronald.Sieber@systec-electronic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/epl/demo_main.c b/drivers/staging/epl/demo_main.c
new file mode 100644
index 0000000..24e4b71
--- /dev/null
+++ b/drivers/staging/epl/demo_main.c
@@ -0,0 +1,937 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: demoapplication for EPL MN (with SDO over UDP)
+ under Linux on X86 with RTL8139 Ethernet controller
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: demo_main.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.10 $ $Date: 2008/11/19 18:11:43 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/09/01 d.k.: start of implementation
+
+****************************************************************************/
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/sched.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+
+
+#include "Epl.h"
+#include "proc_fs.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ // remove ("make invisible") obsolete symbols for kernel versions 2.6
+ // and higher
+ #define MOD_INC_USE_COUNT
+ #define MOD_DEC_USE_COUNT
+ #define EXPORT_NO_SYMBOLS
+#else
+ #error "This driver needs a 2.6.x kernel or higher"
+#endif
+
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+// Metainformation
+MODULE_LICENSE("Dual BSD/GPL");
+#ifdef MODULE_AUTHOR
+ MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
+ MODULE_DESCRIPTION("EPL MN demo");
+#endif
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+ void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p);
+ #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#else
+ #define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#endif
+
+#define NODEID 0xF0 //=> MN
+#define CYCLE_LEN 5000 // [us]
+#define IP_ADDR 0xc0a86401 // 192.168.100.1
+#define SUBNET_MASK 0xFFFFFF00 // 255.255.255.0
+#define HOSTNAME "SYS TEC electronic EPL Stack "
+#define IF_ETH EPL_VETH_NAME
+
+
+// LIGHT EFFECT
+#define DEFAULT_MAX_CYCLE_COUNT 20 // 6 is very fast
+#define APP_DEFAULT_MODE 0x01
+#define APP_LED_COUNT 5 // number of LEDs in one row
+#define APP_LED_MASK ((1 << APP_LED_COUNT) - 1)
+#define APP_DOUBLE_LED_MASK ((1 << (APP_LED_COUNT * 2)) - 1)
+#define APP_MODE_COUNT 5
+#define APP_MODE_MASK ((1 << APP_MODE_COUNT) - 1)
+
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+CONST BYTE abMacAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+BYTE bVarIn1_l;
+BYTE bVarOut1_l;
+BYTE bVarOut1Old_l;
+BYTE bModeSelect_l; // state of the pushbuttons to select the mode
+BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed
+BYTE bSpeedSelectOld_l; // old state of the pushbuttons
+DWORD dwLeds_l; // current state of all LEDs
+BYTE bLedsRow1_l; // current state of the LEDs in row 1
+BYTE bLedsRow2_l; // current state of the LEDs in row 2
+BYTE abSelect_l[3]; // pushbuttons from CNs
+
+DWORD dwMode_l; // current mode
+int iCurCycleCount_l; // current cycle count
+int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step)
+int iToggle; // indicates the light movement direction
+
+BYTE abDomain_l[3000];
+
+static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff
+static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
+
+static DWORD dw_le_CycleLen_g;
+
+static uint uiNodeId_g = EPL_C_ADR_INVALID;
+module_param_named(nodeid, uiNodeId_g, uint, 0);
+
+static uint uiCycleLen_g = CYCLE_LEN;
+module_param_named(cyclelen, uiCycleLen_g, uint, 0);
+
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+// This function is the entry point for your object dictionary. It is defined
+// in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define
+// this function prototype here. If you want to use more than one Epl
+// instances then the function name of each object dictionary has to differ.
+
+tEplKernel PUBLIC EplObdInitRam (tEplObdInitParam MEM* pInitParam_p);
+
+tEplKernel PUBLIC AppCbEvent(
+ tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg* pEventArg_p, // IN: event argument (union)
+ void GENERIC* pUserArg_p);
+
+tEplKernel PUBLIC AppCbSync(void);
+
+static int __init EplLinInit (void);
+static void __exit EplLinExit (void);
+
+//---------------------------------------------------------------------------
+// Kernel Module specific Data Structures
+//---------------------------------------------------------------------------
+
+EXPORT_NO_SYMBOLS;
+
+
+//module_init(EplLinInit);
+//module_exit(EplLinExit);
+
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static int __init EplLinInit (void)
+{
+tEplKernel EplRet;
+int iRet;
+static tEplApiInitParam EplApiInitParam = {0};
+char* sHostname = HOSTNAME;
+char* argv[4], *envp[3];
+char sBuffer[16];
+unsigned int uiVarEntries;
+tEplObdSize ObdSize;
+
+ atomic_set(&AtomicShutdown_g, TRUE);
+
+ // get node ID from insmod command line
+ EplApiInitParam.m_uiNodeId = uiNodeId_g;
+
+ if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID)
+ { // invalid node ID set
+ // set default node ID
+ EplApiInitParam.m_uiNodeId = NODEID;
+ }
+
+ uiNodeId_g = EplApiInitParam.m_uiNodeId;
+
+ // calculate IP address
+ EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
+
+ EplApiInitParam.m_fAsyncOnly = FALSE;
+
+ EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam);
+ EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress));
+// EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId;
+ EplApiInitParam.m_dwFeatureFlags = -1;
+ EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection
+ EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const
+ EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const
+ EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes
+ EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes)
+ EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes)
+ EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes
+ EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection
+ EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size
+ EplApiInitParam.m_uiPrescaler = 2; // required for sync
+ EplApiInitParam.m_dwLossOfFrameTolerance = 500000;
+ EplApiInitParam.m_dwAsyncSlotTimeout = 3000000;
+ EplApiInitParam.m_dwWaitSocPreq = 150000;
+ EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32
+ EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32
+ EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32
+ EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32
+ EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32
+ EplApiInitParam.m_dwSubnetMask = SUBNET_MASK;
+ EplApiInitParam.m_dwDefaultGateway = 0;
+ EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname));
+
+ // currently unset parameters left at default value 0
+ //EplApiInitParam.m_qwVendorSpecificExt1;
+ //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
+ //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
+ //EplApiInitParam.m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
+ //EplApiInitParam.m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
+ //EplApiInitParam.m_abVendorSpecificExt2[48];
+
+ // set callback functions
+ EplApiInitParam.m_pfnCbEvent = AppCbEvent;
+ EplApiInitParam.m_pfnCbSync = AppCbSync;
+
+
+ printk("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n",
+ (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID ?
+ "Managing Node" : "Controlled Node"),
+ __DATE__, __TIME__);
+
+ // initialize the Linux a wait queue for shutdown of this module
+ init_waitqueue_head(&WaitQueueShutdown_g);
+
+ // initialize the procfs device
+ EplRet = EplLinProcInit();
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ // initialize POWERLINK stack
+ EplRet = EplApiInitialize(&EplApiInitParam);
+ if(EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ // link process variables used by CN to object dictionary
+ ObdSize = sizeof(bVarIn1_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bVarOut1_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize, 0x01);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ // link process variables used by MN to object dictionary
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ ObdSize = sizeof(bLedsRow1_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize, 0x01);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bLedsRow2_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize, 0x02);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bSpeedSelect_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize, 0x03);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bSpeedSelectOld_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries, &ObdSize, 0x04);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(abSelect_l[0]);
+ uiVarEntries = sizeof(abSelect_l);
+ EplRet = EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize, 0x01);
+ if (EplRet != kEplSuccessful)
+ {
+ goto Exit;
+ }
+#endif
+
+ // link a DOMAIN to object 0x6100, but do not exit, if it is missing
+ ObdSize = sizeof(abDomain_l);
+ uiVarEntries = 1;
+ EplRet = EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize, 0x00);
+ if (EplRet != kEplSuccessful)
+ {
+ printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
+ }
+
+ // reset old process variables
+ bVarOut1Old_l = 0;
+ bSpeedSelectOld_l = 0;
+ dwMode_l = APP_DEFAULT_MODE;
+ iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
+
+
+ // configure IP address of virtual network interface
+ // for TCP/IP communication over the POWERLINK network
+ sprintf(sBuffer, "%lu.%lu.%lu.%lu", (EplApiInitParam.m_dwIpAddress >> 24), ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF), ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF), (EplApiInitParam.m_dwIpAddress & 0xFF));
+ /* set up a minimal environment */
+ iRet = 0;
+ envp[iRet++] = "HOME=/";
+ envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[iRet] = NULL;
+
+ /* set up the argument list */
+ iRet = 0;
+ argv[iRet++] = "/sbin/ifconfig";
+ argv[iRet++] = IF_ETH;
+ argv[iRet++] = sBuffer;
+ argv[iRet] = NULL;
+
+ /* call ifconfig to configure the virtual network interface */
+ iRet = call_usermodehelper(argv[0], argv, envp, 1);
+ printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet);
+
+ // start the NMT state machine
+ EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
+ atomic_set(&AtomicShutdown_g, FALSE);
+
+Exit:
+ printk("EplLinInit(): returns 0x%X\n", EplRet);
+ return EplRet;
+}
+
+static void __exit EplLinExit (void)
+{
+tEplKernel EplRet;
+
+ // halt the NMT state machine
+ // so the processing of POWERLINK frames stops
+ EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
+
+ // wait until NMT state machine is shut down
+ wait_event_interruptible(WaitQueueShutdown_g,
+ (atomic_read(&AtomicShutdown_g) == TRUE));
+/* if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL))
+ { // waiting was interrupted by signal or application called wrong function
+ EplRet = kEplShutdown;
+ }*/
+ // delete instance for all modules
+ EplRet = EplApiShutdown();
+ printk("EplApiShutdown(): 0x%X\n", EplRet);
+
+ // deinitialize proc fs
+ EplRet = EplLinProcFree();
+ printk("EplLinProcFree(): 0x%X\n", EplRet);
+
+}
+
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: AppCbEvent
+//
+// Description: event callback function called by EPL API layer within
+// user part (low priority).
+//
+// Parameters: EventType_p = event type
+// pEventArg_p = pointer to union, which describes
+// the event in detail
+// pUserArg_p = user specific argument
+//
+// Returns: tEplKernel = error code,
+// kEplSuccessful = no error
+// kEplReject = reject further processing
+// otherwise = post error event to API layer
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC AppCbEvent(
+ tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg* pEventArg_p, // IN: event argument (union)
+ void GENERIC* pUserArg_p)
+{
+tEplKernel EplRet = kEplSuccessful;
+
+ // check if NMT_GS_OFF is reached
+ switch (EventType_p)
+ {
+ case kEplApiEventNmtStateChange:
+ {
+ switch (pEventArg_p->m_NmtStateChange.m_NewNmtState)
+ {
+ case kEplNmtGsOff:
+ { // NMT state machine was shut down,
+ // because of user signal (CTRL-C) or critical EPL stack error
+ // -> also shut down EplApiProcess() and main()
+ EplRet = kEplShutdown;
+
+ printk("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n", pEventArg_p->m_NmtStateChange.m_NmtEvent);
+
+ // wake up EplLinExit()
+ atomic_set(&AtomicShutdown_g, TRUE);
+ wake_up_interruptible(&WaitQueueShutdown_g);
+ break;
+ }
+
+ case kEplNmtGsResetCommunication:
+ {
+ DWORD dwBuffer;
+
+ // configure OD for MN in state ResetComm after reseting the OD
+ // TODO: setup your own network configuration here
+ dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); // 0x00000003L
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x01, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x02, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x03, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x04, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x05, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x06, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x07, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x08, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x20, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0xFE, &dwBuffer, 4);
+ EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
+
+// dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN; // 0x0000000BL
+// EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
+ dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS); // 0x00010001L
+ EplRet = EplApiWriteLocalObject(0x1F81, 0xF0, &dwBuffer, 4);
+
+ // continue
+ }
+
+ case kEplNmtGsResetConfiguration:
+ {
+ unsigned int uiSize;
+
+ // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
+ // for configuration of remote CN
+ uiSize = 4;
+ EplRet = EplApiReadObject(NULL, 0, 0x1006, 0x00, &dw_le_CycleLen_g, &uiSize, kEplSdoTypeAsnd, NULL);
+ if (EplRet != kEplSuccessful)
+ { // local OD access failed
+ break;
+ }
+
+ // continue
+ }
+
+ case kEplNmtMsPreOperational1:
+ {
+ printk("AppCbEvent(0x%X) originating event = 0x%X\n",
+ pEventArg_p->m_NmtStateChange.m_NewNmtState,
+ pEventArg_p->m_NmtStateChange.m_NmtEvent);
+
+ // continue
+ }
+
+ case kEplNmtGsInitialising:
+ case kEplNmtGsResetApplication:
+ case kEplNmtMsNotActive:
+ case kEplNmtCsNotActive:
+ case kEplNmtCsPreOperational1:
+ {
+ break;
+ }
+
+ case kEplNmtCsOperational:
+ case kEplNmtMsOperational:
+ {
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+/*
+ switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
+ {
+ case kEplNmtEventSwReset:
+ case kEplNmtEventResetNode:
+ case kEplNmtEventResetCom:
+ case kEplNmtEventResetConfig:
+ case kEplNmtEventInternComError:
+ case kEplNmtEventNmtCycleError:
+ {
+ printk("AppCbEvent(0x%X) originating event = 0x%X\n",
+ pEventArg_p->m_NmtStateChange.m_NewNmtState,
+ pEventArg_p->m_NmtStateChange.m_NmtEvent);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+*/
+ break;
+ }
+
+ case kEplApiEventCriticalError:
+ case kEplApiEventWarning:
+ { // error or warning occured within the stack or the application
+ // on error the API layer stops the NMT state machine
+
+ printk("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
+ // check additional argument
+ switch (pEventArg_p->m_InternalError.m_EventSource)
+ {
+ case kEplEventSourceEventk:
+ case kEplEventSourceEventu:
+ { // error occured within event processing
+ // either in kernel or in user part
+ printk(" OrgSource=%02X\n", pEventArg_p->m_InternalError.m_Arg.m_EventSource);
+ break;
+ }
+
+ case kEplEventSourceDllk:
+ { // error occured within the data link layer (e.g. interrupt processing)
+ // the DWORD argument contains the DLL state and the NMT event
+ printk(" val=%lX\n", pEventArg_p->m_InternalError.m_Arg.m_dwArg);
+ break;
+ }
+
+ default:
+ {
+ printk("\n");
+ break;
+ }
+ }
+ break;
+ }
+
+ case kEplApiEventNode:
+ {
+// printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
+ // check additional argument
+ switch (pEventArg_p->m_Node.m_NodeEvent)
+ {
+ case kEplNmtNodeEventCheckConf:
+ {
+ tEplSdoComConHdl SdoComConHdl;
+ // update object 0x1006 on CN
+ EplRet = EplApiWriteObject(&SdoComConHdl, pEventArg_p->m_Node.m_uiNodeId, 0x1006, 0x00, &dw_le_CycleLen_g, 4, kEplSdoTypeAsnd, NULL);
+ if (EplRet == kEplApiTaskDeferred)
+ { // SDO transfer started
+ EplRet = kEplReject;
+ }
+ else if (EplRet == kEplSuccessful)
+ { // local OD access (should not occur)
+ printk("AppCbEvent(Node) write to local OD\n");
+ }
+ else
+ { // error occured
+ TGT_DBG_SIGNAL_TRACE_POINT(1);
+
+ EplRet = EplApiFreeSdoChannel(SdoComConHdl);
+ SdoComConHdl = 0;
+
+ EplRet = EplApiWriteObject(&SdoComConHdl, pEventArg_p->m_Node.m_uiNodeId, 0x1006, 0x00, &dw_le_CycleLen_g, 4, kEplSdoTypeAsnd, NULL);
+ if (EplRet == kEplApiTaskDeferred)
+ { // SDO transfer started
+ EplRet = kEplReject;
+ }
+ else
+ {
+ printk("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n", EplRet);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ case kEplApiEventSdo:
+ { // SDO transfer finished
+ EplRet = EplApiFreeSdoChannel(pEventArg_p->m_Sdo.m_SdoComConHdl);
+ if (EplRet != kEplSuccessful)
+ {
+ break;
+ }
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished)
+ { // continue boot-up of CN with NMT command Reset Configuration
+ EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfReset);
+ }
+ else
+ { // indicate configuration error CN
+ EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfErr);
+ }
+#endif
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return EplRet;
+}
+
+
+//---------------------------------------------------------------------------
+//
+// Function: AppCbSync
+//
+// Description: sync event callback function called by event module within
+// kernel part (high priority).
+// This function sets the outputs, reads the inputs and runs
+// the control loop.
+//
+// Parameters: void
+//
+// Returns: tEplKernel = error code,
+// kEplSuccessful = no error
+// otherwise = post error event to API layer
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC AppCbSync(void)
+{
+tEplKernel EplRet = kEplSuccessful;
+
+ if (bVarOut1Old_l != bVarOut1_l)
+ { // output variable has changed
+ bVarOut1Old_l = bVarOut1_l;
+ // set LEDs
+
+// printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l);
+ }
+ if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID)
+ {
+ bVarIn1_l++;
+ }
+
+ if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID)
+ { // we are the master and must run the control loop
+
+ // collect inputs from CNs and own input
+ bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
+
+ bModeSelect_l = abSelect_l[1] | abSelect_l[2];
+
+ if ((bModeSelect_l & APP_MODE_MASK) != 0)
+ {
+ dwMode_l = bModeSelect_l & APP_MODE_MASK;
+ }
+
+ iCurCycleCount_l--;
+
+ if (iCurCycleCount_l <= 0)
+ {
+ if ((dwMode_l & 0x01) != 0)
+ { // fill-up
+ if (iToggle)
+ {
+ if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00)
+ {
+ dwLeds_l = 0x01;
+ }
+ else
+ {
+ dwLeds_l <<= 1;
+ dwLeds_l++;
+ if (dwLeds_l >= APP_DOUBLE_LED_MASK)
+ {
+ iToggle = 0;
+ }
+ }
+ }
+ else
+ {
+ dwLeds_l <<= 1;
+ if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00)
+ {
+ iToggle = 1;
+ }
+ }
+ bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
+ bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
+ }
+
+ else if ((dwMode_l & 0x02) != 0)
+ { // running light forward
+ dwLeds_l <<= 1;
+ if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L))
+ {
+ dwLeds_l = 0x01;
+ }
+ bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
+ bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
+ }
+
+ else if ((dwMode_l & 0x04) != 0)
+ { // running light backward
+ dwLeds_l >>= 1;
+ if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L))
+ {
+ dwLeds_l = 1 << (APP_LED_COUNT * 2);
+ }
+ bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
+ bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
+ }
+
+ else if ((dwMode_l & 0x08) != 0)
+ { // Knightrider
+ if (bLedsRow1_l == 0x00)
+ {
+ bLedsRow1_l = 0x01;
+ iToggle = 1;
+ }
+ else if (iToggle)
+ {
+ bLedsRow1_l <<= 1;
+ if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) )
+ {
+ iToggle = 0;
+ }
+ }
+ else
+ {
+ bLedsRow1_l >>= 1;
+ if( bLedsRow1_l <= 0x01 )
+ {
+ iToggle = 1;
+ }
+ }
+ bLedsRow2_l = bLedsRow1_l;
+ }
+
+ else if ((dwMode_l & 0x10) != 0)
+ { // Knightrider
+ if ((bLedsRow1_l == 0x00)
+ || (bLedsRow2_l == 0x00)
+ || ((bLedsRow2_l & ~APP_LED_MASK) != 0))
+ {
+ bLedsRow1_l = 0x01;
+ bLedsRow2_l = (1 << (APP_LED_COUNT - 1));
+ iToggle = 1;
+ }
+ else if (iToggle)
+ {
+ bLedsRow1_l <<= 1;
+ bLedsRow2_l >>= 1;
+ if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) )
+ {
+ iToggle = 0;
+ }
+ }
+ else
+ {
+ bLedsRow1_l >>= 1;
+ bLedsRow2_l <<= 1;
+ if ( bLedsRow1_l <= 0x01 )
+ {
+ iToggle = 1;
+ }
+ }
+ }
+
+ // set own output
+ bVarOut1_l = bLedsRow1_l;
+// bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
+
+ // restart cycle counter
+ iCurCycleCount_l = iMaxCycleCount_l;
+ }
+
+ if (bSpeedSelectOld_l == 0)
+ {
+ if ((bSpeedSelect_l & 0x01) != 0)
+ {
+ if (iMaxCycleCount_l < 200)
+ {
+ iMaxCycleCount_l++;
+ }
+ bSpeedSelectOld_l = bSpeedSelect_l;
+ }
+ else if ((bSpeedSelect_l & 0x02) != 0)
+ {
+ if (iMaxCycleCount_l > 1)
+ {
+ iMaxCycleCount_l--;
+ }
+ bSpeedSelectOld_l = bSpeedSelect_l;
+ }
+ else if ((bSpeedSelect_l & 0x04) != 0)
+ {
+ iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
+ bSpeedSelectOld_l = bSpeedSelect_l;
+ }
+ }
+ else if (bSpeedSelect_l == 0)
+ {
+ bSpeedSelectOld_l = 0;
+ }
+ }
+
+ TGT_DBG_SIGNAL_TRACE_POINT(1);
+
+ return EplRet;
+}
+
+
+
+// EOF
+