blob: 24e4b710ad05941206fa56a2cc065b57dd7e3216 [file] [log] [blame]
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001/****************************************************************************
2
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
5
6 Project: openPOWERLINK
7
8 Description: demoapplication for EPL MN (with SDO over UDP)
9 under Linux on X86 with RTL8139 Ethernet controller
10
11 License:
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
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.
23
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.
28
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.
41
42 Severability Clause:
43
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.
50
51 -------------------------------------------------------------------------
52
53 $RCSfile: demo_main.c,v $
54
55 $Author: D.Krueger $
56
57 $Revision: 1.10 $ $Date: 2008/11/19 18:11:43 $
58
59 $State: Exp $
60
61 Build Environment:
62 GCC
63
64 -------------------------------------------------------------------------
65
66 Revision History:
67
68 2006/09/01 d.k.: start of implementation
69
70****************************************************************************/
71
72
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>
79#include <asm/io.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>
87
88
89#include "Epl.h"
90#include "proc_fs.h"
91
92#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
93 // remove ("make invisible") obsolete symbols for kernel versions 2.6
94 // and higher
95 #define MOD_INC_USE_COUNT
96 #define MOD_DEC_USE_COUNT
97 #define EXPORT_NO_SYMBOLS
98#else
99 #error "This driver needs a 2.6.x kernel or higher"
100#endif
101
102
103/***************************************************************************/
104/* */
105/* */
106/* G L O B A L D E F I N I T I O N S */
107/* */
108/* */
109/***************************************************************************/
110
111// Metainformation
112MODULE_LICENSE("Dual BSD/GPL");
113#ifdef MODULE_AUTHOR
114 MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
115 MODULE_DESCRIPTION("EPL MN demo");
116#endif
117
118//---------------------------------------------------------------------------
119// const defines
120//---------------------------------------------------------------------------
121
122
123
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)
128#else
129 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
130#endif
131
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
138
139
140// LIGHT EFFECT
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)
148
149
150//---------------------------------------------------------------------------
151// local types
152//---------------------------------------------------------------------------
153
154
155
156//---------------------------------------------------------------------------
157// modul globale vars
158//---------------------------------------------------------------------------
159
160CONST BYTE abMacAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
161
162BYTE bVarIn1_l;
163BYTE bVarOut1_l;
164BYTE bVarOut1Old_l;
165BYTE bModeSelect_l; // state of the pushbuttons to select the mode
166BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed
167BYTE bSpeedSelectOld_l; // old state of the pushbuttons
168DWORD dwLeds_l; // current state of all LEDs
169BYTE bLedsRow1_l; // current state of the LEDs in row 1
170BYTE bLedsRow2_l; // current state of the LEDs in row 2
171BYTE abSelect_l[3]; // pushbuttons from CNs
172
173DWORD dwMode_l; // current mode
174int iCurCycleCount_l; // current cycle count
175int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step)
176int iToggle; // indicates the light movement direction
177
178BYTE abDomain_l[3000];
179
180static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff
181static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
182
183static DWORD dw_le_CycleLen_g;
184
185static uint uiNodeId_g = EPL_C_ADR_INVALID;
186module_param_named(nodeid, uiNodeId_g, uint, 0);
187
188static uint uiCycleLen_g = CYCLE_LEN;
189module_param_named(cyclelen, uiCycleLen_g, uint, 0);
190
191
192//---------------------------------------------------------------------------
193// local function prototypes
194//---------------------------------------------------------------------------
195
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.
200
201tEplKernel PUBLIC EplObdInitRam (tEplObdInitParam MEM* pInitParam_p);
202
203tEplKernel PUBLIC AppCbEvent(
204 tEplApiEventType EventType_p, // IN: event type (enum)
205 tEplApiEventArg* pEventArg_p, // IN: event argument (union)
206 void GENERIC* pUserArg_p);
207
208tEplKernel PUBLIC AppCbSync(void);
209
210static int __init EplLinInit (void);
211static void __exit EplLinExit (void);
212
213//---------------------------------------------------------------------------
214// Kernel Module specific Data Structures
215//---------------------------------------------------------------------------
216
217EXPORT_NO_SYMBOLS;
218
219
220//module_init(EplLinInit);
221//module_exit(EplLinExit);
222
223
224//=========================================================================//
225// //
226// P U B L I C F U N C T I O N S //
227// //
228//=========================================================================//
229
230//---------------------------------------------------------------------------
231//
232// Function:
233//
234// Description:
235//
236//
237//
238// Parameters:
239//
240//
241// Returns:
242//
243//
244// State:
245//
246//---------------------------------------------------------------------------
247static int __init EplLinInit (void)
248{
249tEplKernel EplRet;
250int iRet;
251static tEplApiInitParam EplApiInitParam = {0};
252char* sHostname = HOSTNAME;
253char* argv[4], *envp[3];
254char sBuffer[16];
255unsigned int uiVarEntries;
256tEplObdSize ObdSize;
257
258 atomic_set(&AtomicShutdown_g, TRUE);
259
260 // get node ID from insmod command line
261 EplApiInitParam.m_uiNodeId = uiNodeId_g;
262
263 if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID)
264 { // invalid node ID set
265 // set default node ID
266 EplApiInitParam.m_uiNodeId = NODEID;
267 }
268
269 uiNodeId_g = EplApiInitParam.m_uiNodeId;
270
271 // calculate IP address
272 EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
273
274 EplApiInitParam.m_fAsyncOnly = FALSE;
275
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));
301
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];
309
310 // set callback functions
311 EplApiInitParam.m_pfnCbEvent = AppCbEvent;
312 EplApiInitParam.m_pfnCbSync = AppCbSync;
313
314
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"),
318 __DATE__, __TIME__);
319
320 // initialize the Linux a wait queue for shutdown of this module
321 init_waitqueue_head(&WaitQueueShutdown_g);
322
323 // initialize the procfs device
324 EplRet = EplLinProcInit();
325 if (EplRet != kEplSuccessful)
326 {
327 goto Exit;
328 }
329
330 // initialize POWERLINK stack
331 EplRet = EplApiInitialize(&EplApiInitParam);
332 if(EplRet != kEplSuccessful)
333 {
334 goto Exit;
335 }
336
337 // link process variables used by CN to object dictionary
338 ObdSize = sizeof(bVarIn1_l);
339 uiVarEntries = 1;
340 EplRet = EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
341 if (EplRet != kEplSuccessful)
342 {
343 goto Exit;
344 }
345
346 ObdSize = sizeof(bVarOut1_l);
347 uiVarEntries = 1;
348 EplRet = EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize, 0x01);
349 if (EplRet != kEplSuccessful)
350 {
351 goto Exit;
352 }
353
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);
357 uiVarEntries = 1;
358 EplRet = EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize, 0x01);
359 if (EplRet != kEplSuccessful)
360 {
361 goto Exit;
362 }
363
364 ObdSize = sizeof(bLedsRow2_l);
365 uiVarEntries = 1;
366 EplRet = EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize, 0x02);
367 if (EplRet != kEplSuccessful)
368 {
369 goto Exit;
370 }
371
372 ObdSize = sizeof(bSpeedSelect_l);
373 uiVarEntries = 1;
374 EplRet = EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize, 0x03);
375 if (EplRet != kEplSuccessful)
376 {
377 goto Exit;
378 }
379
380 ObdSize = sizeof(bSpeedSelectOld_l);
381 uiVarEntries = 1;
382 EplRet = EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries, &ObdSize, 0x04);
383 if (EplRet != kEplSuccessful)
384 {
385 goto Exit;
386 }
387
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)
392 {
393 goto Exit;
394 }
395#endif
396
397 // link a DOMAIN to object 0x6100, but do not exit, if it is missing
398 ObdSize = sizeof(abDomain_l);
399 uiVarEntries = 1;
400 EplRet = EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize, 0x00);
401 if (EplRet != kEplSuccessful)
402 {
403 printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
404 }
405
406 // reset old process variables
407 bVarOut1Old_l = 0;
408 bSpeedSelectOld_l = 0;
409 dwMode_l = APP_DEFAULT_MODE;
410 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
411
412
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 */
417 iRet = 0;
418 envp[iRet++] = "HOME=/";
419 envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
420 envp[iRet] = NULL;
421
422 /* set up the argument list */
423 iRet = 0;
424 argv[iRet++] = "/sbin/ifconfig";
425 argv[iRet++] = IF_ETH;
426 argv[iRet++] = sBuffer;
427 argv[iRet] = NULL;
428
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);
432
433 // start the NMT state machine
434 EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
435 atomic_set(&AtomicShutdown_g, FALSE);
436
437Exit:
438 printk("EplLinInit(): returns 0x%X\n", EplRet);
439 return EplRet;
440}
441
442static void __exit EplLinExit (void)
443{
444tEplKernel EplRet;
445
446 // halt the NMT state machine
447 // so the processing of POWERLINK frames stops
448 EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
449
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;
456 }*/
457 // delete instance for all modules
458 EplRet = EplApiShutdown();
459 printk("EplApiShutdown(): 0x%X\n", EplRet);
460
461 // deinitialize proc fs
462 EplRet = EplLinProcFree();
463 printk("EplLinProcFree(): 0x%X\n", EplRet);
464
465}
466
467
468//=========================================================================//
469// //
470// P R I V A T E F U N C T I O N S //
471// //
472//=========================================================================//
473
474//---------------------------------------------------------------------------
475//
476// Function: AppCbEvent
477//
478// Description: event callback function called by EPL API layer within
479// user part (low priority).
480//
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
485//
486// Returns: tEplKernel = error code,
487// kEplSuccessful = no error
488// kEplReject = reject further processing
489// otherwise = post error event to API layer
490//
491// State:
492//
493//---------------------------------------------------------------------------
494
495tEplKernel PUBLIC AppCbEvent(
496 tEplApiEventType EventType_p, // IN: event type (enum)
497 tEplApiEventArg* pEventArg_p, // IN: event argument (union)
498 void GENERIC* pUserArg_p)
499{
500tEplKernel EplRet = kEplSuccessful;
501
502 // check if NMT_GS_OFF is reached
503 switch (EventType_p)
504 {
505 case kEplApiEventNmtStateChange:
506 {
507 switch (pEventArg_p->m_NmtStateChange.m_NewNmtState)
508 {
509 case kEplNmtGsOff:
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;
514
515 printk("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n", pEventArg_p->m_NmtStateChange.m_NmtEvent);
516
517 // wake up EplLinExit()
518 atomic_set(&AtomicShutdown_g, TRUE);
519 wake_up_interruptible(&WaitQueueShutdown_g);
520 break;
521 }
522
523 case kEplNmtGsResetCommunication:
524 {
525 DWORD dwBuffer;
526
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);
541
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);
546
547 // continue
548 }
549
550 case kEplNmtGsResetConfiguration:
551 {
552 unsigned int uiSize;
553
554 // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
555 // for configuration of remote CN
556 uiSize = 4;
557 EplRet = EplApiReadObject(NULL, 0, 0x1006, 0x00, &dw_le_CycleLen_g, &uiSize, kEplSdoTypeAsnd, NULL);
558 if (EplRet != kEplSuccessful)
559 { // local OD access failed
560 break;
561 }
562
563 // continue
564 }
565
566 case kEplNmtMsPreOperational1:
567 {
568 printk("AppCbEvent(0x%X) originating event = 0x%X\n",
569 pEventArg_p->m_NmtStateChange.m_NewNmtState,
570 pEventArg_p->m_NmtStateChange.m_NmtEvent);
571
572 // continue
573 }
574
575 case kEplNmtGsInitialising:
576 case kEplNmtGsResetApplication:
577 case kEplNmtMsNotActive:
578 case kEplNmtCsNotActive:
579 case kEplNmtCsPreOperational1:
580 {
581 break;
582 }
583
584 case kEplNmtCsOperational:
585 case kEplNmtMsOperational:
586 {
587 break;
588 }
589
590 default:
591 {
592 break;
593 }
594 }
595
596/*
597 switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
598 {
599 case kEplNmtEventSwReset:
600 case kEplNmtEventResetNode:
601 case kEplNmtEventResetCom:
602 case kEplNmtEventResetConfig:
603 case kEplNmtEventInternComError:
604 case kEplNmtEventNmtCycleError:
605 {
606 printk("AppCbEvent(0x%X) originating event = 0x%X\n",
607 pEventArg_p->m_NmtStateChange.m_NewNmtState,
608 pEventArg_p->m_NmtStateChange.m_NmtEvent);
609 break;
610 }
611
612 default:
613 {
614 break;
615 }
616 }
617*/
618 break;
619 }
620
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
625
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)
629 {
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);
635 break;
636 }
637
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);
642 break;
643 }
644
645 default:
646 {
647 printk("\n");
648 break;
649 }
650 }
651 break;
652 }
653
654 case kEplApiEventNode:
655 {
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)
659 {
660 case kEplNmtNodeEventCheckConf:
661 {
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
667 EplRet = kEplReject;
668 }
669 else if (EplRet == kEplSuccessful)
670 { // local OD access (should not occur)
671 printk("AppCbEvent(Node) write to local OD\n");
672 }
673 else
674 { // error occured
675 TGT_DBG_SIGNAL_TRACE_POINT(1);
676
677 EplRet = EplApiFreeSdoChannel(SdoComConHdl);
678 SdoComConHdl = 0;
679
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
683 EplRet = kEplReject;
684 }
685 else
686 {
687 printk("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n", EplRet);
688 }
689 }
690
691 break;
692 }
693
694 default:
695 {
696 break;
697 }
698 }
699 break;
700 }
701
702 case kEplApiEventSdo:
703 { // SDO transfer finished
704 EplRet = EplApiFreeSdoChannel(pEventArg_p->m_Sdo.m_SdoComConHdl);
705 if (EplRet != kEplSuccessful)
706 {
707 break;
708 }
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);
713 }
714 else
715 { // indicate configuration error CN
716 EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfErr);
717 }
718#endif
719
720 break;
721 }
722
723 default:
724 break;
725 }
726
727 return EplRet;
728}
729
730
731//---------------------------------------------------------------------------
732//
733// Function: AppCbSync
734//
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
738// the control loop.
739//
740// Parameters: void
741//
742// Returns: tEplKernel = error code,
743// kEplSuccessful = no error
744// otherwise = post error event to API layer
745//
746// State:
747//
748//---------------------------------------------------------------------------
749
750tEplKernel PUBLIC AppCbSync(void)
751{
752tEplKernel EplRet = kEplSuccessful;
753
754 if (bVarOut1Old_l != bVarOut1_l)
755 { // output variable has changed
756 bVarOut1Old_l = bVarOut1_l;
757 // set LEDs
758
759// printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l);
760 }
761 if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID)
762 {
763 bVarIn1_l++;
764 }
765
766 if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID)
767 { // we are the master and must run the control loop
768
769 // collect inputs from CNs and own input
770 bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
771
772 bModeSelect_l = abSelect_l[1] | abSelect_l[2];
773
774 if ((bModeSelect_l & APP_MODE_MASK) != 0)
775 {
776 dwMode_l = bModeSelect_l & APP_MODE_MASK;
777 }
778
779 iCurCycleCount_l--;
780
781 if (iCurCycleCount_l <= 0)
782 {
783 if ((dwMode_l & 0x01) != 0)
784 { // fill-up
785 if (iToggle)
786 {
787 if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00)
788 {
789 dwLeds_l = 0x01;
790 }
791 else
792 {
793 dwLeds_l <<= 1;
794 dwLeds_l++;
795 if (dwLeds_l >= APP_DOUBLE_LED_MASK)
796 {
797 iToggle = 0;
798 }
799 }
800 }
801 else
802 {
803 dwLeds_l <<= 1;
804 if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00)
805 {
806 iToggle = 1;
807 }
808 }
809 bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
810 bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
811 }
812
813 else if ((dwMode_l & 0x02) != 0)
814 { // running light forward
815 dwLeds_l <<= 1;
816 if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L))
817 {
818 dwLeds_l = 0x01;
819 }
820 bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
821 bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
822 }
823
824 else if ((dwMode_l & 0x04) != 0)
825 { // running light backward
826 dwLeds_l >>= 1;
827 if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L))
828 {
829 dwLeds_l = 1 << (APP_LED_COUNT * 2);
830 }
831 bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK);
832 bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK);
833 }
834
835 else if ((dwMode_l & 0x08) != 0)
836 { // Knightrider
837 if (bLedsRow1_l == 0x00)
838 {
839 bLedsRow1_l = 0x01;
840 iToggle = 1;
841 }
842 else if (iToggle)
843 {
844 bLedsRow1_l <<= 1;
845 if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) )
846 {
847 iToggle = 0;
848 }
849 }
850 else
851 {
852 bLedsRow1_l >>= 1;
853 if( bLedsRow1_l <= 0x01 )
854 {
855 iToggle = 1;
856 }
857 }
858 bLedsRow2_l = bLedsRow1_l;
859 }
860
861 else if ((dwMode_l & 0x10) != 0)
862 { // Knightrider
863 if ((bLedsRow1_l == 0x00)
864 || (bLedsRow2_l == 0x00)
865 || ((bLedsRow2_l & ~APP_LED_MASK) != 0))
866 {
867 bLedsRow1_l = 0x01;
868 bLedsRow2_l = (1 << (APP_LED_COUNT - 1));
869 iToggle = 1;
870 }
871 else if (iToggle)
872 {
873 bLedsRow1_l <<= 1;
874 bLedsRow2_l >>= 1;
875 if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) )
876 {
877 iToggle = 0;
878 }
879 }
880 else
881 {
882 bLedsRow1_l >>= 1;
883 bLedsRow2_l <<= 1;
884 if ( bLedsRow1_l <= 0x01 )
885 {
886 iToggle = 1;
887 }
888 }
889 }
890
891 // set own output
892 bVarOut1_l = bLedsRow1_l;
893// bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
894
895 // restart cycle counter
896 iCurCycleCount_l = iMaxCycleCount_l;
897 }
898
899 if (bSpeedSelectOld_l == 0)
900 {
901 if ((bSpeedSelect_l & 0x01) != 0)
902 {
903 if (iMaxCycleCount_l < 200)
904 {
905 iMaxCycleCount_l++;
906 }
907 bSpeedSelectOld_l = bSpeedSelect_l;
908 }
909 else if ((bSpeedSelect_l & 0x02) != 0)
910 {
911 if (iMaxCycleCount_l > 1)
912 {
913 iMaxCycleCount_l--;
914 }
915 bSpeedSelectOld_l = bSpeedSelect_l;
916 }
917 else if ((bSpeedSelect_l & 0x04) != 0)
918 {
919 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
920 bSpeedSelectOld_l = bSpeedSelect_l;
921 }
922 }
923 else if (bSpeedSelect_l == 0)
924 {
925 bSpeedSelectOld_l = 0;
926 }
927 }
928
929 TGT_DBG_SIGNAL_TRACE_POINT(1);
930
931 return EplRet;
932}
933
934
935
936// EOF
937