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 ****************************************************************************/
72 #include <linux/module.h>
73 #include <linux/kernel.h>
74 #include <linux/init.h>
75 #include <linux/errno.h>
76 #include <linux/major.h>
77 #include <linux/version.h>
79 #include <asm/uaccess.h>
80 #include <asm/atomic.h>
81 #include <linux/sched.h>
82 #include <linux/kmod.h>
83 #include <linux/slab.h>
84 #include <linux/pci.h>
85 #include <linux/proc_fs.h>
90 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
91 // remove ("make invisible") obsolete symbols for kernel versions 2.6
93 #define MOD_INC_USE_COUNT
94 #define MOD_DEC_USE_COUNT
95 #define EXPORT_NO_SYMBOLS
97 #error "This driver needs a 2.6.x kernel or higher"
100 /***************************************************************************/
103 /* G L O B A L D E F I N I T I O N S */
106 /***************************************************************************/
109 MODULE_LICENSE("Dual BSD/GPL");
111 MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
112 MODULE_DESCRIPTION("EPL MN demo");
115 //---------------------------------------------------------------------------
117 //---------------------------------------------------------------------------
119 // TracePoint support for realtime-debugging
120 #ifdef _DBG_TRACE_POINTS_
121 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
122 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
124 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
127 #define NODEID 0xF0 //=> MN
128 #define CYCLE_LEN 5000 // [us]
129 #define IP_ADDR 0xc0a86401 // 192.168.100.1
130 #define SUBNET_MASK 0xFFFFFF00 // 255.255.255.0
131 #define HOSTNAME "SYS TEC electronic EPL Stack "
132 #define IF_ETH EPL_VETH_NAME
135 #define DEFAULT_MAX_CYCLE_COUNT 20 // 6 is very fast
136 #define APP_DEFAULT_MODE 0x01
137 #define APP_LED_COUNT 5 // number of LEDs in one row
138 #define APP_LED_MASK ((1 << APP_LED_COUNT) - 1)
139 #define APP_DOUBLE_LED_MASK ((1 << (APP_LED_COUNT * 2)) - 1)
140 #define APP_MODE_COUNT 5
141 #define APP_MODE_MASK ((1 << APP_MODE_COUNT) - 1)
143 //---------------------------------------------------------------------------
145 //---------------------------------------------------------------------------
147 //---------------------------------------------------------------------------
148 // modul globale vars
149 //---------------------------------------------------------------------------
151 CONST BYTE abMacAddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
156 BYTE bModeSelect_l; // state of the pushbuttons to select the mode
157 BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed
158 BYTE bSpeedSelectOld_l; // old state of the pushbuttons
159 DWORD dwLeds_l; // current state of all LEDs
160 BYTE bLedsRow1_l; // current state of the LEDs in row 1
161 BYTE bLedsRow2_l; // current state of the LEDs in row 2
162 BYTE abSelect_l[3]; // pushbuttons from CNs
164 DWORD dwMode_l; // current mode
165 int iCurCycleCount_l; // current cycle count
166 int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step)
167 int iToggle; // indicates the light movement direction
169 BYTE abDomain_l[3000];
171 static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff
172 static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
174 static DWORD dw_le_CycleLen_g;
176 static uint uiNodeId_g = EPL_C_ADR_INVALID;
177 module_param_named(nodeid, uiNodeId_g, uint, 0);
179 static uint uiCycleLen_g = CYCLE_LEN;
180 module_param_named(cyclelen, uiCycleLen_g, uint, 0);
182 //---------------------------------------------------------------------------
183 // local function prototypes
184 //---------------------------------------------------------------------------
186 // This function is the entry point for your object dictionary. It is defined
187 // in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define
188 // this function prototype here. If you want to use more than one Epl
189 // instances then the function name of each object dictionary has to differ.
191 tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p);
193 tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
194 tEplApiEventArg * pEventArg_p, // IN: event argument (union)
195 void GENERIC * pUserArg_p);
197 tEplKernel PUBLIC AppCbSync(void);
199 static int __init EplLinInit(void);
200 static void __exit EplLinExit(void);
202 //---------------------------------------------------------------------------
203 // Kernel Module specific Data Structures
204 //---------------------------------------------------------------------------
208 //module_init(EplLinInit);
209 //module_exit(EplLinExit);
211 //=========================================================================//
213 // P U B L I C F U N C T I O N S //
215 //=========================================================================//
217 //---------------------------------------------------------------------------
233 //---------------------------------------------------------------------------
234 static int __init EplLinInit(void)
238 static tEplApiInitParam EplApiInitParam = { 0 };
239 char *sHostname = HOSTNAME;
240 char *argv[4], *envp[3];
242 unsigned int uiVarEntries;
245 atomic_set(&AtomicShutdown_g, TRUE);
247 // get node ID from insmod command line
248 EplApiInitParam.m_uiNodeId = uiNodeId_g;
250 if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) { // invalid node ID set
251 // set default node ID
252 EplApiInitParam.m_uiNodeId = NODEID;
255 uiNodeId_g = EplApiInitParam.m_uiNodeId;
257 // calculate IP address
258 EplApiInitParam.m_dwIpAddress =
259 (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
261 EplApiInitParam.m_fAsyncOnly = FALSE;
263 EplApiInitParam.m_uiSizeOfStruct = sizeof(EplApiInitParam);
264 EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr,
265 sizeof(EplApiInitParam.m_abMacAddress));
266 // EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId;
267 EplApiInitParam.m_dwFeatureFlags = -1;
268 EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection
269 EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const
270 EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const
271 EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes
272 EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes)
273 EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes)
274 EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes
275 EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection
276 EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size
277 EplApiInitParam.m_uiPrescaler = 2; // required for sync
278 EplApiInitParam.m_dwLossOfFrameTolerance = 500000;
279 EplApiInitParam.m_dwAsyncSlotTimeout = 3000000;
280 EplApiInitParam.m_dwWaitSocPreq = 150000;
281 EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32
282 EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32
283 EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32
284 EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32
285 EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32
286 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK;
287 EplApiInitParam.m_dwDefaultGateway = 0;
288 EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname,
289 sizeof(EplApiInitParam.m_sHostname));
291 // currently unset parameters left at default value 0
292 //EplApiInitParam.m_qwVendorSpecificExt1;
293 //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
294 //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
295 //EplApiInitParam.m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
296 //EplApiInitParam.m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
297 //EplApiInitParam.m_abVendorSpecificExt2[48];
299 // set callback functions
300 EplApiInitParam.m_pfnCbEvent = AppCbEvent;
301 EplApiInitParam.m_pfnCbSync = AppCbSync;
304 ("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n",
306 EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"),
309 // initialize the Linux a wait queue for shutdown of this module
310 init_waitqueue_head(&WaitQueueShutdown_g);
312 // initialize the procfs device
313 EplRet = EplLinProcInit();
314 if (EplRet != kEplSuccessful) {
317 // initialize POWERLINK stack
318 EplRet = EplApiInitialize(&EplApiInitParam);
319 if (EplRet != kEplSuccessful) {
322 // link process variables used by CN to object dictionary
323 ObdSize = sizeof(bVarIn1_l);
326 EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
327 if (EplRet != kEplSuccessful) {
331 ObdSize = sizeof(bVarOut1_l);
334 EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize,
336 if (EplRet != kEplSuccessful) {
339 // link process variables used by MN to object dictionary
340 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
341 ObdSize = sizeof(bLedsRow1_l);
344 EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize,
346 if (EplRet != kEplSuccessful) {
350 ObdSize = sizeof(bLedsRow2_l);
353 EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize,
355 if (EplRet != kEplSuccessful) {
359 ObdSize = sizeof(bSpeedSelect_l);
362 EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize,
364 if (EplRet != kEplSuccessful) {
368 ObdSize = sizeof(bSpeedSelectOld_l);
371 EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries,
373 if (EplRet != kEplSuccessful) {
377 ObdSize = sizeof(abSelect_l[0]);
378 uiVarEntries = sizeof(abSelect_l);
380 EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize,
382 if (EplRet != kEplSuccessful) {
387 // link a DOMAIN to object 0x6100, but do not exit, if it is missing
388 ObdSize = sizeof(abDomain_l);
391 EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize,
393 if (EplRet != kEplSuccessful) {
394 printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
396 // reset old process variables
398 bSpeedSelectOld_l = 0;
399 dwMode_l = APP_DEFAULT_MODE;
400 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
402 // configure IP address of virtual network interface
403 // for TCP/IP communication over the POWERLINK network
404 sprintf(sBuffer, "%lu.%lu.%lu.%lu",
405 (EplApiInitParam.m_dwIpAddress >> 24),
406 ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF),
407 ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF),
408 (EplApiInitParam.m_dwIpAddress & 0xFF));
409 /* set up a minimal environment */
411 envp[iRet++] = "HOME=/";
412 envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
415 /* set up the argument list */
417 argv[iRet++] = "/sbin/ifconfig";
418 argv[iRet++] = IF_ETH;
419 argv[iRet++] = sBuffer;
422 /* call ifconfig to configure the virtual network interface */
423 iRet = call_usermodehelper(argv[0], argv, envp, 1);
424 printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet);
426 // start the NMT state machine
427 EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
428 atomic_set(&AtomicShutdown_g, FALSE);
431 printk("EplLinInit(): returns 0x%X\n", EplRet);
435 static void __exit EplLinExit(void)
439 // halt the NMT state machine
440 // so the processing of POWERLINK frames stops
441 EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
443 // wait until NMT state machine is shut down
444 wait_event_interruptible(WaitQueueShutdown_g,
445 (atomic_read(&AtomicShutdown_g) == TRUE));
446 /* if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL))
447 { // waiting was interrupted by signal or application called wrong function
448 EplRet = kEplShutdown;
450 // delete instance for all modules
451 EplRet = EplApiShutdown();
452 printk("EplApiShutdown(): 0x%X\n", EplRet);
454 // deinitialize proc fs
455 EplRet = EplLinProcFree();
456 printk("EplLinProcFree(): 0x%X\n", EplRet);
460 //=========================================================================//
462 // P R I V A T E F U N C T I O N S //
464 //=========================================================================//
466 //---------------------------------------------------------------------------
468 // Function: AppCbEvent
470 // Description: event callback function called by EPL API layer within
471 // user part (low priority).
473 // Parameters: EventType_p = event type
474 // pEventArg_p = pointer to union, which describes
475 // the event in detail
476 // pUserArg_p = user specific argument
478 // Returns: tEplKernel = error code,
479 // kEplSuccessful = no error
480 // kEplReject = reject further processing
481 // otherwise = post error event to API layer
485 //---------------------------------------------------------------------------
487 tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
488 tEplApiEventArg * pEventArg_p, // IN: event argument (union)
489 void GENERIC * pUserArg_p)
491 tEplKernel EplRet = kEplSuccessful;
493 // check if NMT_GS_OFF is reached
494 switch (EventType_p) {
495 case kEplApiEventNmtStateChange:
497 switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) {
499 { // NMT state machine was shut down,
500 // because of user signal (CTRL-C) or critical EPL stack error
501 // -> also shut down EplApiProcess() and main()
502 EplRet = kEplShutdown;
505 ("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n",
506 pEventArg_p->m_NmtStateChange.
509 // wake up EplLinExit()
510 atomic_set(&AtomicShutdown_g, TRUE);
511 wake_up_interruptible
512 (&WaitQueueShutdown_g);
516 case kEplNmtGsResetCommunication:
520 // configure OD for MN in state ResetComm after reseting the OD
521 // TODO: setup your own network configuration here
522 dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); // 0x00000003L
524 EplApiWriteLocalObject(0x1F81, 0x01,
528 EplApiWriteLocalObject(0x1F81, 0x02,
532 EplApiWriteLocalObject(0x1F81, 0x03,
536 EplApiWriteLocalObject(0x1F81, 0x04,
540 EplApiWriteLocalObject(0x1F81, 0x05,
544 EplApiWriteLocalObject(0x1F81, 0x06,
548 EplApiWriteLocalObject(0x1F81, 0x07,
552 EplApiWriteLocalObject(0x1F81, 0x08,
556 EplApiWriteLocalObject(0x1F81, 0x20,
560 EplApiWriteLocalObject(0x1F81, 0xFE,
564 EplApiWriteLocalObject(0x1F81, 0x6E,
568 // dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN; // 0x0000000BL
569 // EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
570 dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS); // 0x00010001L
572 EplApiWriteLocalObject(0x1F81, 0xF0,
579 case kEplNmtGsResetConfiguration:
583 // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
584 // for configuration of remote CN
587 EplApiReadObject(NULL, 0, 0x1006,
593 if (EplRet != kEplSuccessful) { // local OD access failed
599 case kEplNmtMsPreOperational1:
602 ("AppCbEvent(0x%X) originating event = 0x%X\n",
603 pEventArg_p->m_NmtStateChange.
605 pEventArg_p->m_NmtStateChange.
611 case kEplNmtGsInitialising:
612 case kEplNmtGsResetApplication:
613 case kEplNmtMsNotActive:
614 case kEplNmtCsNotActive:
615 case kEplNmtCsPreOperational1:
620 case kEplNmtCsOperational:
621 case kEplNmtMsOperational:
633 switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
635 case kEplNmtEventSwReset:
636 case kEplNmtEventResetNode:
637 case kEplNmtEventResetCom:
638 case kEplNmtEventResetConfig:
639 case kEplNmtEventInternComError:
640 case kEplNmtEventNmtCycleError:
642 printk("AppCbEvent(0x%X) originating event = 0x%X\n",
643 pEventArg_p->m_NmtStateChange.m_NewNmtState,
644 pEventArg_p->m_NmtStateChange.m_NmtEvent);
657 case kEplApiEventCriticalError:
658 case kEplApiEventWarning:
659 { // error or warning occured within the stack or the application
660 // on error the API layer stops the NMT state machine
663 ("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X",
664 pEventArg_p->m_InternalError.m_EventSource,
665 pEventArg_p->m_InternalError.m_EplError);
666 // check additional argument
667 switch (pEventArg_p->m_InternalError.m_EventSource) {
668 case kEplEventSourceEventk:
669 case kEplEventSourceEventu:
670 { // error occured within event processing
671 // either in kernel or in user part
672 printk(" OrgSource=%02X\n",
673 pEventArg_p->m_InternalError.
674 m_Arg.m_EventSource);
678 case kEplEventSourceDllk:
679 { // error occured within the data link layer (e.g. interrupt processing)
680 // the DWORD argument contains the DLL state and the NMT event
682 pEventArg_p->m_InternalError.
696 case kEplApiEventNode:
698 // printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
699 // check additional argument
700 switch (pEventArg_p->m_Node.m_NodeEvent) {
701 case kEplNmtNodeEventCheckConf:
703 tEplSdoComConHdl SdoComConHdl;
704 // update object 0x1006 on CN
706 EplApiWriteObject(&SdoComConHdl,
714 if (EplRet == kEplApiTaskDeferred) { // SDO transfer started
716 } else if (EplRet == kEplSuccessful) { // local OD access (should not occur)
718 ("AppCbEvent(Node) write to local OD\n");
719 } else { // error occured
720 TGT_DBG_SIGNAL_TRACE_POINT(1);
731 m_uiNodeId, 0x1006, 0x00,
732 &dw_le_CycleLen_g, 4,
733 kEplSdoTypeAsnd, NULL);
734 if (EplRet == kEplApiTaskDeferred) { // SDO transfer started
738 ("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n",
754 case kEplApiEventSdo:
755 { // SDO transfer finished
757 EplApiFreeSdoChannel(pEventArg_p->m_Sdo.
759 if (EplRet != kEplSuccessful) {
762 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
763 if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished) { // continue boot-up of CN with NMT command Reset Configuration
765 EplApiMnTriggerStateChange(pEventArg_p->
767 kEplNmtNodeCommandConfReset);
768 } else { // indicate configuration error CN
770 EplApiMnTriggerStateChange(pEventArg_p->
772 kEplNmtNodeCommandConfErr);
786 //---------------------------------------------------------------------------
788 // Function: AppCbSync
790 // Description: sync event callback function called by event module within
791 // kernel part (high priority).
792 // This function sets the outputs, reads the inputs and runs
797 // Returns: tEplKernel = error code,
798 // kEplSuccessful = no error
799 // otherwise = post error event to API layer
803 //---------------------------------------------------------------------------
805 tEplKernel PUBLIC AppCbSync(void)
807 tEplKernel EplRet = kEplSuccessful;
809 if (bVarOut1Old_l != bVarOut1_l) { // output variable has changed
810 bVarOut1Old_l = bVarOut1_l;
813 // printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l);
815 if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID) {
819 if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID) { // we are the master and must run the control loop
821 // collect inputs from CNs and own input
822 bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
824 bModeSelect_l = abSelect_l[1] | abSelect_l[2];
826 if ((bModeSelect_l & APP_MODE_MASK) != 0) {
827 dwMode_l = bModeSelect_l & APP_MODE_MASK;
832 if (iCurCycleCount_l <= 0) {
833 if ((dwMode_l & 0x01) != 0) { // fill-up
835 if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
842 APP_DOUBLE_LED_MASK) {
848 if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
854 (unsigned char)(dwLeds_l & APP_LED_MASK);
856 (unsigned char)((dwLeds_l >> APP_LED_COUNT)
860 else if ((dwMode_l & 0x02) != 0) { // running light forward
862 if ((dwLeds_l > APP_DOUBLE_LED_MASK)
863 || (dwLeds_l == 0x00000000L)) {
867 (unsigned char)(dwLeds_l & APP_LED_MASK);
869 (unsigned char)((dwLeds_l >> APP_LED_COUNT)
873 else if ((dwMode_l & 0x04) != 0) { // running light backward
875 if ((dwLeds_l > APP_DOUBLE_LED_MASK)
876 || (dwLeds_l == 0x00000000L)) {
877 dwLeds_l = 1 << (APP_LED_COUNT * 2);
880 (unsigned char)(dwLeds_l & APP_LED_MASK);
882 (unsigned char)((dwLeds_l >> APP_LED_COUNT)
886 else if ((dwMode_l & 0x08) != 0) { // Knightrider
887 if (bLedsRow1_l == 0x00) {
890 } else if (iToggle) {
893 (1 << (APP_LED_COUNT - 1))) {
898 if (bLedsRow1_l <= 0x01) {
902 bLedsRow2_l = bLedsRow1_l;
905 else if ((dwMode_l & 0x10) != 0) { // Knightrider
906 if ((bLedsRow1_l == 0x00)
907 || (bLedsRow2_l == 0x00)
908 || ((bLedsRow2_l & ~APP_LED_MASK) != 0)) {
911 (1 << (APP_LED_COUNT - 1));
913 } else if (iToggle) {
917 (1 << (APP_LED_COUNT - 1))) {
923 if (bLedsRow1_l <= 0x01) {
929 bVarOut1_l = bLedsRow1_l;
930 // bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
932 // restart cycle counter
933 iCurCycleCount_l = iMaxCycleCount_l;
936 if (bSpeedSelectOld_l == 0) {
937 if ((bSpeedSelect_l & 0x01) != 0) {
938 if (iMaxCycleCount_l < 200) {
941 bSpeedSelectOld_l = bSpeedSelect_l;
942 } else if ((bSpeedSelect_l & 0x02) != 0) {
943 if (iMaxCycleCount_l > 1) {
946 bSpeedSelectOld_l = bSpeedSelect_l;
947 } else if ((bSpeedSelect_l & 0x04) != 0) {
948 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
949 bSpeedSelectOld_l = bSpeedSelect_l;
951 } else if (bSpeedSelect_l == 0) {
952 bSpeedSelectOld_l = 0;
956 TGT_DBG_SIGNAL_TRACE_POINT(1);