1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: demoapplication for EPL MN (with SDO over UDP)
9 under Linux on X86 with RTL8139 Ethernet controller
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
24 3. Neither the name of SYSTEC electronic GmbH nor the names of its
25 contributors may be used to endorse or promote products derived
26 from this software without prior written permission. For written
27 permission, please contact info@systec-electronic.com.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 POSSIBILITY OF SUCH DAMAGE.
44 If a provision of this License is or becomes illegal, invalid or
45 unenforceable in any jurisdiction, that shall not affect:
46 1. the validity or enforceability in that jurisdiction of any other
47 provision of this License; or
48 2. the validity or enforceability in other jurisdictions of that or
49 any other provision of this License.
51 -------------------------------------------------------------------------
53 $RCSfile: demo_main.c,v $
57 $Revision: 1.10 $ $Date: 2008/11/19 18:11:43 $
64 -------------------------------------------------------------------------
68 2006/09/01 d.k.: start of implementation
70 ****************************************************************************/
73 #include <linux/module.h>
74 #include <linux/kernel.h>
75 #include <linux/init.h>
76 #include <linux/errno.h>
77 #include <linux/major.h>
78 #include <linux/version.h>
80 #include <asm/uaccess.h>
81 #include <asm/atomic.h>
82 #include <linux/sched.h>
83 #include <linux/kmod.h>
84 #include <linux/slab.h>
85 #include <linux/pci.h>
86 #include <linux/proc_fs.h>
92 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
93 // remove ("make invisible") obsolete symbols for kernel versions 2.6
95 #define MOD_INC_USE_COUNT
96 #define MOD_DEC_USE_COUNT
97 #define EXPORT_NO_SYMBOLS
99 #error "This driver needs a 2.6.x kernel or higher"
103 /***************************************************************************/
106 /* G L O B A L D E F I N I T I O N S */
109 /***************************************************************************/
112 MODULE_LICENSE("Dual BSD/GPL");
114 MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
115 MODULE_DESCRIPTION("EPL MN demo");
118 //---------------------------------------------------------------------------
120 //---------------------------------------------------------------------------
124 // TracePoint support for realtime-debugging
125 #ifdef _DBG_TRACE_POINTS_
126 void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p);
127 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
129 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
132 #define NODEID 0xF0 //=> MN
133 #define CYCLE_LEN 5000 // [us]
134 #define IP_ADDR 0xc0a86401 // 192.168.100.1
135 #define SUBNET_MASK 0xFFFFFF00 // 255.255.255.0
136 #define HOSTNAME "SYS TEC electronic EPL Stack "
137 #define IF_ETH EPL_VETH_NAME
141 #define DEFAULT_MAX_CYCLE_COUNT 20 // 6 is very fast
142 #define APP_DEFAULT_MODE 0x01
143 #define APP_LED_COUNT 5 // number of LEDs in one row
144 #define APP_LED_MASK ((1 << APP_LED_COUNT) - 1)
145 #define APP_DOUBLE_LED_MASK ((1 << (APP_LED_COUNT * 2)) - 1)
146 #define APP_MODE_COUNT 5
147 #define APP_MODE_MASK ((1 << APP_MODE_COUNT) - 1)
150 //---------------------------------------------------------------------------
152 //---------------------------------------------------------------------------
156 //---------------------------------------------------------------------------
157 // modul globale vars
158 //---------------------------------------------------------------------------
160 CONST BYTE abMacAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
165 BYTE bModeSelect_l; // state of the pushbuttons to select the mode
166 BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed
167 BYTE bSpeedSelectOld_l; // old state of the pushbuttons
168 DWORD dwLeds_l; // current state of all LEDs
169 BYTE bLedsRow1_l; // current state of the LEDs in row 1
170 BYTE bLedsRow2_l; // current state of the LEDs in row 2
171 BYTE abSelect_l[3]; // pushbuttons from CNs
173 DWORD dwMode_l; // current mode
174 int iCurCycleCount_l; // current cycle count
175 int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step)
176 int iToggle; // indicates the light movement direction
178 BYTE abDomain_l[3000];
180 static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff
181 static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
183 static DWORD dw_le_CycleLen_g;
185 static uint uiNodeId_g = EPL_C_ADR_INVALID;
186 module_param_named(nodeid, uiNodeId_g, uint, 0);
188 static uint uiCycleLen_g = CYCLE_LEN;
189 module_param_named(cyclelen, uiCycleLen_g, uint, 0);
192 //---------------------------------------------------------------------------
193 // local function prototypes
194 //---------------------------------------------------------------------------
196 // This function is the entry point for your object dictionary. It is defined
197 // in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define
198 // this function prototype here. If you want to use more than one Epl
199 // instances then the function name of each object dictionary has to differ.
201 tEplKernel PUBLIC EplObdInitRam (tEplObdInitParam MEM* pInitParam_p);
203 tEplKernel PUBLIC AppCbEvent(
204 tEplApiEventType EventType_p, // IN: event type (enum)
205 tEplApiEventArg* pEventArg_p, // IN: event argument (union)
206 void GENERIC* pUserArg_p);
208 tEplKernel PUBLIC AppCbSync(void);
210 static int __init EplLinInit (void);
211 static void __exit EplLinExit (void);
213 //---------------------------------------------------------------------------
214 // Kernel Module specific Data Structures
215 //---------------------------------------------------------------------------
220 //module_init(EplLinInit);
221 //module_exit(EplLinExit);
224 //=========================================================================//
226 // P U B L I C F U N C T I O N S //
228 //=========================================================================//
230 //---------------------------------------------------------------------------
246 //---------------------------------------------------------------------------
247 static int __init EplLinInit (void)
251 static tEplApiInitParam EplApiInitParam = {0};
252 char* sHostname = HOSTNAME;
253 char* argv[4], *envp[3];
255 unsigned int uiVarEntries;
258 atomic_set(&AtomicShutdown_g, TRUE);
260 // get node ID from insmod command line
261 EplApiInitParam.m_uiNodeId = uiNodeId_g;
263 if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID)
264 { // invalid node ID set
265 // set default node ID
266 EplApiInitParam.m_uiNodeId = NODEID;
269 uiNodeId_g = EplApiInitParam.m_uiNodeId;
271 // calculate IP address
272 EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
274 EplApiInitParam.m_fAsyncOnly = FALSE;
276 EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam);
277 EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress));
278 // EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId;
279 EplApiInitParam.m_dwFeatureFlags = -1;
280 EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection
281 EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const
282 EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const
283 EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes
284 EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes)
285 EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes)
286 EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes
287 EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection
288 EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size
289 EplApiInitParam.m_uiPrescaler = 2; // required for sync
290 EplApiInitParam.m_dwLossOfFrameTolerance = 500000;
291 EplApiInitParam.m_dwAsyncSlotTimeout = 3000000;
292 EplApiInitParam.m_dwWaitSocPreq = 150000;
293 EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32
294 EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32
295 EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32
296 EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32
297 EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32
298 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK;
299 EplApiInitParam.m_dwDefaultGateway = 0;
300 EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname));
302 // currently unset parameters left at default value 0
303 //EplApiInitParam.m_qwVendorSpecificExt1;
304 //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
305 //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
306 //EplApiInitParam.m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
307 //EplApiInitParam.m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
308 //EplApiInitParam.m_abVendorSpecificExt2[48];
310 // set callback functions
311 EplApiInitParam.m_pfnCbEvent = AppCbEvent;
312 EplApiInitParam.m_pfnCbSync = AppCbSync;
315 printk("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n",
316 (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID ?
317 "Managing Node" : "Controlled Node"),
320 // initialize the Linux a wait queue for shutdown of this module
321 init_waitqueue_head(&WaitQueueShutdown_g);
323 // initialize the procfs device
324 EplRet = EplLinProcInit();
325 if (EplRet != kEplSuccessful)
330 // initialize POWERLINK stack
331 EplRet = EplApiInitialize(&EplApiInitParam);
332 if(EplRet != kEplSuccessful)
337 // link process variables used by CN to object dictionary
338 ObdSize = sizeof(bVarIn1_l);
340 EplRet = EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
341 if (EplRet != kEplSuccessful)
346 ObdSize = sizeof(bVarOut1_l);
348 EplRet = EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize, 0x01);
349 if (EplRet != kEplSuccessful)
354 // link process variables used by MN to object dictionary
355 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
356 ObdSize = sizeof(bLedsRow1_l);
358 EplRet = EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize, 0x01);
359 if (EplRet != kEplSuccessful)
364 ObdSize = sizeof(bLedsRow2_l);
366 EplRet = EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize, 0x02);
367 if (EplRet != kEplSuccessful)
372 ObdSize = sizeof(bSpeedSelect_l);
374 EplRet = EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize, 0x03);
375 if (EplRet != kEplSuccessful)
380 ObdSize = sizeof(bSpeedSelectOld_l);
382 EplRet = EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries, &ObdSize, 0x04);
383 if (EplRet != kEplSuccessful)
388 ObdSize = sizeof(abSelect_l[0]);
389 uiVarEntries = sizeof(abSelect_l);
390 EplRet = EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize, 0x01);
391 if (EplRet != kEplSuccessful)
397 // link a DOMAIN to object 0x6100, but do not exit, if it is missing
398 ObdSize = sizeof(abDomain_l);
400 EplRet = EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize, 0x00);
401 if (EplRet != kEplSuccessful)
403 printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
406 // reset old process variables
408 bSpeedSelectOld_l = 0;
409 dwMode_l = APP_DEFAULT_MODE;
410 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
413 // configure IP address of virtual network interface
414 // for TCP/IP communication over the POWERLINK network
415 sprintf(sBuffer, "%lu.%lu.%lu.%lu", (EplApiInitParam.m_dwIpAddress >> 24), ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF), ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF), (EplApiInitParam.m_dwIpAddress & 0xFF));
416 /* set up a minimal environment */
418 envp[iRet++] = "HOME=/";
419 envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
422 /* set up the argument list */
424 argv[iRet++] = "/sbin/ifconfig";
425 argv[iRet++] = IF_ETH;
426 argv[iRet++] = sBuffer;
429 /* call ifconfig to configure the virtual network interface */
430 iRet = call_usermodehelper(argv[0], argv, envp, 1);
431 printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet);
433 // start the NMT state machine
434 EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
435 atomic_set(&AtomicShutdown_g, FALSE);
438 printk("EplLinInit(): returns 0x%X\n", EplRet);
442 static void __exit EplLinExit (void)
446 // halt the NMT state machine
447 // so the processing of POWERLINK frames stops
448 EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
450 // wait until NMT state machine is shut down
451 wait_event_interruptible(WaitQueueShutdown_g,
452 (atomic_read(&AtomicShutdown_g) == TRUE));
453 /* if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL))
454 { // waiting was interrupted by signal or application called wrong function
455 EplRet = kEplShutdown;
457 // delete instance for all modules
458 EplRet = EplApiShutdown();
459 printk("EplApiShutdown(): 0x%X\n", EplRet);
461 // deinitialize proc fs
462 EplRet = EplLinProcFree();
463 printk("EplLinProcFree(): 0x%X\n", EplRet);
468 //=========================================================================//
470 // P R I V A T E F U N C T I O N S //
472 //=========================================================================//
474 //---------------------------------------------------------------------------
476 // Function: AppCbEvent
478 // Description: event callback function called by EPL API layer within
479 // user part (low priority).
481 // Parameters: EventType_p = event type
482 // pEventArg_p = pointer to union, which describes
483 // the event in detail
484 // pUserArg_p = user specific argument
486 // Returns: tEplKernel = error code,
487 // kEplSuccessful = no error
488 // kEplReject = reject further processing
489 // otherwise = post error event to API layer
493 //---------------------------------------------------------------------------
495 tEplKernel PUBLIC AppCbEvent(
496 tEplApiEventType EventType_p, // IN: event type (enum)
497 tEplApiEventArg* pEventArg_p, // IN: event argument (union)
498 void GENERIC* pUserArg_p)
500 tEplKernel EplRet = kEplSuccessful;
502 // check if NMT_GS_OFF is reached
505 case kEplApiEventNmtStateChange:
507 switch (pEventArg_p->m_NmtStateChange.m_NewNmtState)
510 { // NMT state machine was shut down,
511 // because of user signal (CTRL-C) or critical EPL stack error
512 // -> also shut down EplApiProcess() and main()
513 EplRet = kEplShutdown;
515 printk("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n", pEventArg_p->m_NmtStateChange.m_NmtEvent);
517 // wake up EplLinExit()
518 atomic_set(&AtomicShutdown_g, TRUE);
519 wake_up_interruptible(&WaitQueueShutdown_g);
523 case kEplNmtGsResetCommunication:
527 // configure OD for MN in state ResetComm after reseting the OD
528 // TODO: setup your own network configuration here
529 dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); // 0x00000003L
530 EplRet = EplApiWriteLocalObject(0x1F81, 0x01, &dwBuffer, 4);
531 EplRet = EplApiWriteLocalObject(0x1F81, 0x02, &dwBuffer, 4);
532 EplRet = EplApiWriteLocalObject(0x1F81, 0x03, &dwBuffer, 4);
533 EplRet = EplApiWriteLocalObject(0x1F81, 0x04, &dwBuffer, 4);
534 EplRet = EplApiWriteLocalObject(0x1F81, 0x05, &dwBuffer, 4);
535 EplRet = EplApiWriteLocalObject(0x1F81, 0x06, &dwBuffer, 4);
536 EplRet = EplApiWriteLocalObject(0x1F81, 0x07, &dwBuffer, 4);
537 EplRet = EplApiWriteLocalObject(0x1F81, 0x08, &dwBuffer, 4);
538 EplRet = EplApiWriteLocalObject(0x1F81, 0x20, &dwBuffer, 4);
539 EplRet = EplApiWriteLocalObject(0x1F81, 0xFE, &dwBuffer, 4);
540 EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
542 // dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN; // 0x0000000BL
543 // EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
544 dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS); // 0x00010001L
545 EplRet = EplApiWriteLocalObject(0x1F81, 0xF0, &dwBuffer, 4);
550 case kEplNmtGsResetConfiguration:
554 // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
555 // for configuration of remote CN
557 EplRet = EplApiReadObject(NULL, 0, 0x1006, 0x00, &dw_le_CycleLen_g, &uiSize, kEplSdoTypeAsnd, NULL);
558 if (EplRet != kEplSuccessful)
559 { // local OD access failed
566 case kEplNmtMsPreOperational1:
568 printk("AppCbEvent(0x%X) originating event = 0x%X\n",
569 pEventArg_p->m_NmtStateChange.m_NewNmtState,
570 pEventArg_p->m_NmtStateChange.m_NmtEvent);
575 case kEplNmtGsInitialising:
576 case kEplNmtGsResetApplication:
577 case kEplNmtMsNotActive:
578 case kEplNmtCsNotActive:
579 case kEplNmtCsPreOperational1:
584 case kEplNmtCsOperational:
585 case kEplNmtMsOperational:
597 switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
599 case kEplNmtEventSwReset:
600 case kEplNmtEventResetNode:
601 case kEplNmtEventResetCom:
602 case kEplNmtEventResetConfig:
603 case kEplNmtEventInternComError:
604 case kEplNmtEventNmtCycleError:
606 printk("AppCbEvent(0x%X) originating event = 0x%X\n",
607 pEventArg_p->m_NmtStateChange.m_NewNmtState,
608 pEventArg_p->m_NmtStateChange.m_NmtEvent);
621 case kEplApiEventCriticalError:
622 case kEplApiEventWarning:
623 { // error or warning occured within the stack or the application
624 // on error the API layer stops the NMT state machine
626 printk("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
627 // check additional argument
628 switch (pEventArg_p->m_InternalError.m_EventSource)
630 case kEplEventSourceEventk:
631 case kEplEventSourceEventu:
632 { // error occured within event processing
633 // either in kernel or in user part
634 printk(" OrgSource=%02X\n", pEventArg_p->m_InternalError.m_Arg.m_EventSource);
638 case kEplEventSourceDllk:
639 { // error occured within the data link layer (e.g. interrupt processing)
640 // the DWORD argument contains the DLL state and the NMT event
641 printk(" val=%lX\n", pEventArg_p->m_InternalError.m_Arg.m_dwArg);
654 case kEplApiEventNode:
656 // printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
657 // check additional argument
658 switch (pEventArg_p->m_Node.m_NodeEvent)
660 case kEplNmtNodeEventCheckConf:
662 tEplSdoComConHdl SdoComConHdl;
663 // update object 0x1006 on CN
664 EplRet = EplApiWriteObject(&SdoComConHdl, pEventArg_p->m_Node.m_uiNodeId, 0x1006, 0x00, &dw_le_CycleLen_g, 4, kEplSdoTypeAsnd, NULL);
665 if (EplRet == kEplApiTaskDeferred)
666 { // SDO transfer started
669 else if (EplRet == kEplSuccessful)
670 { // local OD access (should not occur)
671 printk("AppCbEvent(Node) write to local OD\n");
675 TGT_DBG_SIGNAL_TRACE_POINT(1);
677 EplRet = EplApiFreeSdoChannel(SdoComConHdl);
680 EplRet = EplApiWriteObject(&SdoComConHdl, pEventArg_p->m_Node.m_uiNodeId, 0x1006, 0x00, &dw_le_CycleLen_g, 4, kEplSdoTypeAsnd, NULL);
681 if (EplRet == kEplApiTaskDeferred)
682 { // SDO transfer started
687 printk("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n", EplRet);
702 case kEplApiEventSdo:
703 { // SDO transfer finished
704 EplRet = EplApiFreeSdoChannel(pEventArg_p->m_Sdo.m_SdoComConHdl);
705 if (EplRet != kEplSuccessful)
709 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
710 if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished)
711 { // continue boot-up of CN with NMT command Reset Configuration
712 EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfReset);
715 { // indicate configuration error CN
716 EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfErr);
731 //---------------------------------------------------------------------------
733 // Function: AppCbSync
735 // Description: sync event callback function called by event module within
736 // kernel part (high priority).
737 // This function sets the outputs, reads the inputs and runs
742 // Returns: tEplKernel = error code,
743 // kEplSuccessful = no error
744 // otherwise = post error event to API layer
748 //---------------------------------------------------------------------------
750 tEplKernel PUBLIC AppCbSync(void)
752 tEplKernel EplRet = kEplSuccessful;
754 if (bVarOut1Old_l != bVarOut1_l)
755 { // output variable has changed
756 bVarOut1Old_l = bVarOut1_l;
759 // printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l);
761 if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID)
766 if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID)
767 { // we are the master and must run the control loop
769 // collect inputs from CNs and own input
770 bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
772 bModeSelect_l = abSelect_l[1] | abSelect_l[2];
774 if ((bModeSelect_l & APP_MODE_MASK) != 0)
776 dwMode_l = bModeSelect_l & APP_MODE_MASK;
781 if (iCurCycleCount_l <= 0)
783 if ((dwMode_l & 0x01) != 0)
787 if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00)
795 if (dwLeds_l >= APP_DOUBLE_LED_MASK)
804 if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00)
809 bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
810 bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
813 else if ((dwMode_l & 0x02) != 0)
814 { // running light forward
816 if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L))
820 bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
821 bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
824 else if ((dwMode_l & 0x04) != 0)
825 { // running light backward
827 if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L))
829 dwLeds_l = 1 << (APP_LED_COUNT * 2);
831 bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
832 bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
835 else if ((dwMode_l & 0x08) != 0)
837 if (bLedsRow1_l == 0x00)
845 if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) )
853 if( bLedsRow1_l <= 0x01 )
858 bLedsRow2_l = bLedsRow1_l;
861 else if ((dwMode_l & 0x10) != 0)
863 if ((bLedsRow1_l == 0x00)
864 || (bLedsRow2_l == 0x00)
865 || ((bLedsRow2_l & ~APP_LED_MASK) != 0))
868 bLedsRow2_l = (1 << (APP_LED_COUNT - 1));
875 if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) )
884 if ( bLedsRow1_l <= 0x01 )
892 bVarOut1_l = bLedsRow1_l;
893 // bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
895 // restart cycle counter
896 iCurCycleCount_l = iMaxCycleCount_l;
899 if (bSpeedSelectOld_l == 0)
901 if ((bSpeedSelect_l & 0x01) != 0)
903 if (iMaxCycleCount_l < 200)
907 bSpeedSelectOld_l = bSpeedSelect_l;
909 else if ((bSpeedSelect_l & 0x02) != 0)
911 if (iMaxCycleCount_l > 1)
915 bSpeedSelectOld_l = bSpeedSelect_l;
917 else if ((bSpeedSelect_l & 0x04) != 0)
919 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
920 bSpeedSelectOld_l = bSpeedSelect_l;
923 else if (bSpeedSelect_l == 0)
925 bSpeedSelectOld_l = 0;
929 TGT_DBG_SIGNAL_TRACE_POINT(1);