• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
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:  source file for NMT-Userspace-Module
9 
10   License:
11 
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15 
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18 
19     2. Redistributions in binary form must reproduce the above copyright
20        notice, this list of conditions and the following disclaimer in the
21        documentation and/or other materials provided with the distribution.
22 
23     3. Neither the name of SYSTEC electronic GmbH nor the names of its
24        contributors may be used to endorse or promote products derived
25        from this software without prior written permission. For written
26        permission, please contact info@systec-electronic.com.
27 
28     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32     COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40 
41     Severability Clause:
42 
43         If a provision of this License is or becomes illegal, invalid or
44         unenforceable in any jurisdiction, that shall not affect:
45         1. the validity or enforceability in that jurisdiction of any other
46            provision of this License; or
47         2. the validity or enforceability in other jurisdictions of that or
48            any other provision of this License.
49 
50   -------------------------------------------------------------------------
51 
52                 $RCSfile: EplNmtu.c,v $
53 
54                 $Author: D.Krueger $
55 
56                 $Revision: 1.8 $  $Date: 2008/11/10 17:17:42 $
57 
58                 $State: Exp $
59 
60                 Build Environment:
61                     GCC V3.4
62 
63   -------------------------------------------------------------------------
64 
65   Revision History:
66 
67   2006/06/09 k.t.:   start of the implementation
68 
69 ****************************************************************************/
70 
71 #include "EplInc.h"
72 #include "user/EplNmtu.h"
73 #include "user/EplObdu.h"
74 #include "user/EplTimeru.h"
75 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
76 #include "kernel/EplNmtk.h"
77 #endif
78 
79 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
80 /***************************************************************************/
81 /*                                                                         */
82 /*                                                                         */
83 /*          G L O B A L   D E F I N I T I O N S                            */
84 /*                                                                         */
85 /*                                                                         */
86 /***************************************************************************/
87 
88 //---------------------------------------------------------------------------
89 // const defines
90 //---------------------------------------------------------------------------
91 
92 //---------------------------------------------------------------------------
93 // local types
94 //---------------------------------------------------------------------------
95 
96 typedef struct {
97 	tEplNmtuStateChangeCallback m_pfnNmtChangeCb;
98 	tEplTimerHdl m_TimerHdl;
99 
100 } tEplNmtuInstance;
101 
102 //---------------------------------------------------------------------------
103 // modul globale vars
104 //---------------------------------------------------------------------------
105 
106 static tEplNmtuInstance EplNmtuInstance_g;
107 
108 //---------------------------------------------------------------------------
109 // local function prototypes
110 //---------------------------------------------------------------------------
111 
112 //=========================================================================//
113 //                                                                         //
114 //          P U B L I C   F U N C T I O N S                                //
115 //                                                                         //
116 //=========================================================================//
117 
118 //---------------------------------------------------------------------------
119 //
120 // Function:    EplNmtuInit
121 //
122 // Description: init first instance of the module
123 //
124 //
125 //
126 // Parameters:
127 //
128 //
129 // Returns:     tEplKernel  = errorcode
130 //
131 //
132 // State:
133 //
134 //---------------------------------------------------------------------------
EplNmtuInit()135 EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit()
136 {
137 	tEplKernel Ret;
138 
139 	Ret = EplNmtuAddInstance();
140 
141 	return Ret;
142 }
143 
144 //---------------------------------------------------------------------------
145 //
146 // Function:    EplNmtuAddInstance
147 //
148 // Description: init other instances of the module
149 //
150 //
151 //
152 // Parameters:
153 //
154 //
155 // Returns:     tEplKernel  = errorcode
156 //
157 //
158 // State:
159 //
160 //---------------------------------------------------------------------------
EplNmtuAddInstance()161 EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance()
162 {
163 	tEplKernel Ret;
164 
165 	Ret = kEplSuccessful;
166 
167 	EplNmtuInstance_g.m_pfnNmtChangeCb = NULL;
168 
169 	return Ret;
170 
171 }
172 
173 //---------------------------------------------------------------------------
174 //
175 // Function:    EplNmtuDelInstance
176 //
177 // Description: delete instance
178 //
179 //
180 //
181 // Parameters:
182 //
183 //
184 // Returns:     tEplKernel  = errorcode
185 //
186 //
187 // State:
188 //
189 //---------------------------------------------------------------------------
EplNmtuDelInstance()190 EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance()
191 {
192 	tEplKernel Ret;
193 
194 	Ret = kEplSuccessful;
195 
196 	EplNmtuInstance_g.m_pfnNmtChangeCb = NULL;
197 
198 	// delete timer
199 	Ret = EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl);
200 
201 	return Ret;
202 
203 }
204 
205 //---------------------------------------------------------------------------
206 //
207 // Function:    EplNmtuNmtEvent
208 //
209 // Description: sends the NMT-Event to the NMT-State-Maschine
210 //
211 //
212 //
213 // Parameters:  NmtEvent_p  = NMT-Event to send
214 //
215 //
216 // Returns:     tEplKernel  = errorcode
217 //
218 //
219 // State:
220 //
221 //---------------------------------------------------------------------------
EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p)222 EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p)
223 {
224 	tEplKernel Ret;
225 	tEplEvent Event;
226 
227 	Event.m_EventSink = kEplEventSinkNmtk;
228 	Event.m_NetTime.m_dwNanoSec = 0;
229 	Event.m_NetTime.m_dwSec = 0;
230 	Event.m_EventType = kEplEventTypeNmtEvent;
231 	Event.m_pArg = &NmtEvent_p;
232 	Event.m_uiSize = sizeof(NmtEvent_p);
233 
234 	Ret = EplEventuPost(&Event);
235 
236 	return Ret;
237 }
238 
239 //---------------------------------------------------------------------------
240 //
241 // Function:    EplNmtuGetNmtState
242 //
243 // Description: returns the actuell NMT-State
244 //
245 //
246 //
247 // Parameters:
248 //
249 //
250 // Returns:     tEplNmtState  = NMT-State
251 //
252 //
253 // State:
254 //
255 //---------------------------------------------------------------------------
EplNmtuGetNmtState()256 EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState()
257 {
258 	tEplNmtState NmtState;
259 
260 	// $$$ call function of communication abstraction layer
261 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
262 	NmtState = EplNmtkGetNmtState();
263 #else
264 	NmtState = 0;
265 #endif
266 
267 	return NmtState;
268 }
269 
270 //---------------------------------------------------------------------------
271 //
272 // Function:    EplNmtuProcessEvent
273 //
274 // Description: processes events from event queue
275 //
276 //
277 //
278 // Parameters:  pEplEvent_p =   pointer to event
279 //
280 //
281 // Returns:     tEplKernel  = errorcode
282 //
283 //
284 // State:
285 //
286 //---------------------------------------------------------------------------
EplNmtuProcessEvent(tEplEvent * pEplEvent_p)287 EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p)
288 {
289 	tEplKernel Ret;
290 
291 	Ret = kEplSuccessful;
292 
293 	// process event
294 	switch (pEplEvent_p->m_EventType) {
295 		// state change of NMT-Module
296 	case kEplEventTypeNmtStateChange:
297 		{
298 			tEplEventNmtStateChange *pNmtStateChange;
299 
300 			// delete timer
301 			Ret =
302 			    EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl);
303 
304 			pNmtStateChange =
305 			    (tEplEventNmtStateChange *) pEplEvent_p->m_pArg;
306 
307 			// call cb-functions to inform higher layer
308 			if (EplNmtuInstance_g.m_pfnNmtChangeCb != NULL) {
309 				Ret =
310 				    EplNmtuInstance_g.
311 				    m_pfnNmtChangeCb(*pNmtStateChange);
312 			}
313 
314 			if (Ret == kEplSuccessful) {	// everything is OK, so switch to next state if necessary
315 				switch (pNmtStateChange->m_NewNmtState) {
316 					// EPL stack is not running
317 				case kEplNmtGsOff:
318 					break;
319 
320 					// first init of the hardware
321 				case kEplNmtGsInitialising:
322 					{
323 						Ret =
324 						    EplNmtuNmtEvent
325 						    (kEplNmtEventEnterResetApp);
326 						break;
327 					}
328 
329 					// init of the manufacturer-specific profile area and the
330 					// standardised device profile area
331 				case kEplNmtGsResetApplication:
332 					{
333 						Ret =
334 						    EplNmtuNmtEvent
335 						    (kEplNmtEventEnterResetCom);
336 						break;
337 					}
338 
339 					// init of the communication profile area
340 				case kEplNmtGsResetCommunication:
341 					{
342 						Ret =
343 						    EplNmtuNmtEvent
344 						    (kEplNmtEventEnterResetConfig);
345 						break;
346 					}
347 
348 					// build the configuration with infos from OD
349 				case kEplNmtGsResetConfiguration:
350 					{
351 						unsigned int uiNodeId;
352 
353 						// get node ID from OD
354 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
355 						uiNodeId =
356 						    EplObduGetNodeId
357 						    (EPL_MCO_PTR_INSTANCE_PTR);
358 #else
359 						uiNodeId = 0;
360 #endif
361 						//check node ID if not should be master or slave
362 						if (uiNodeId == EPL_C_ADR_MN_DEF_NODE_ID) {	// node shall be MN
363 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
364 							Ret =
365 							    EplNmtuNmtEvent
366 							    (kEplNmtEventEnterMsNotActive);
367 #else
368 							TRACE0
369 							    ("EplNmtuProcess(): no MN functionality implemented\n");
370 #endif
371 						} else {	// node shall be CN
372 							Ret =
373 							    EplNmtuNmtEvent
374 							    (kEplNmtEventEnterCsNotActive);
375 						}
376 						break;
377 					}
378 
379 					//-----------------------------------------------------------
380 					// CN part of the state machine
381 
382 					// node listens for EPL-Frames and check timeout
383 				case kEplNmtCsNotActive:
384 					{
385 						DWORD dwBuffer;
386 						tEplObdSize ObdSize;
387 						tEplTimerArg TimerArg;
388 
389 						// create timer to switch automatically to BasicEthernet if no MN available in network
390 
391 						// read NMT_CNBasicEthernetTimerout_U32 from OD
392 						ObdSize = sizeof(dwBuffer);
393 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
394 						Ret =
395 						    EplObduReadEntry
396 						    (EPL_MCO_PTR_INSTANCE_PTR_
397 						     0x1F99, 0x00, &dwBuffer,
398 						     &ObdSize);
399 #else
400 						Ret = kEplObdIndexNotExist;
401 #endif
402 						if (Ret != kEplSuccessful) {
403 							break;
404 						}
405 						if (dwBuffer != 0) {	// BasicEthernet is enabled
406 							// convert us into ms
407 							dwBuffer =
408 							    dwBuffer / 1000;
409 							if (dwBuffer == 0) {	// timer was below one ms
410 								// set one ms
411 								dwBuffer = 1;
412 							}
413 							TimerArg.m_EventSink =
414 							    kEplEventSinkNmtk;
415 							TimerArg.m_ulArg =
416 							    (unsigned long)
417 							    kEplNmtEventTimerBasicEthernet;
418 							Ret =
419 							    EplTimeruModifyTimerMs
420 							    (&EplNmtuInstance_g.
421 							     m_TimerHdl,
422 							     (unsigned long)
423 							     dwBuffer,
424 							     TimerArg);
425 							// potential error is forwarded to event queue which generates error event
426 						}
427 						break;
428 					}
429 
430 					// node processes only async frames
431 				case kEplNmtCsPreOperational1:
432 					{
433 						break;
434 					}
435 
436 					// node processes isochronous and asynchronous frames
437 				case kEplNmtCsPreOperational2:
438 					{
439 						Ret =
440 						    EplNmtuNmtEvent
441 						    (kEplNmtEventEnterReadyToOperate);
442 						break;
443 					}
444 
445 					// node should be configured und application is ready
446 				case kEplNmtCsReadyToOperate:
447 					{
448 						break;
449 					}
450 
451 					// normal work state
452 				case kEplNmtCsOperational:
453 					{
454 						break;
455 					}
456 
457 					// node stopped by MN
458 					// -> only process asynchronous frames
459 				case kEplNmtCsStopped:
460 					{
461 						break;
462 					}
463 
464 					// no EPL cycle
465 					// -> normal ethernet communication
466 				case kEplNmtCsBasicEthernet:
467 					{
468 						break;
469 					}
470 
471 					//-----------------------------------------------------------
472 					// MN part of the state machine
473 
474 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
475 					// node listens for EPL-Frames and check timeout
476 				case kEplNmtMsNotActive:
477 					{
478 						DWORD dwBuffer;
479 						tEplObdSize ObdSize;
480 						tEplTimerArg TimerArg;
481 
482 						// create timer to switch automatically to BasicEthernet/PreOp1 if no other MN active in network
483 
484 						// check NMT_StartUp_U32.Bit13
485 						// read NMT_StartUp_U32 from OD
486 						ObdSize = sizeof(dwBuffer);
487 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
488 						Ret =
489 						    EplObduReadEntry
490 						    (EPL_MCO_PTR_INSTANCE_PTR_
491 						     0x1F80, 0x00, &dwBuffer,
492 						     &ObdSize);
493 #else
494 						Ret = kEplObdIndexNotExist;
495 #endif
496 						if (Ret != kEplSuccessful) {
497 							break;
498 						}
499 
500 						if ((dwBuffer & EPL_NMTST_BASICETHERNET) == 0) {	// NMT_StartUp_U32.Bit13 == 0
501 							// new state PreOperational1
502 							TimerArg.m_ulArg =
503 							    (unsigned long)
504 							    kEplNmtEventTimerMsPreOp1;
505 						} else {	// NMT_StartUp_U32.Bit13 == 1
506 							// new state BasicEthernet
507 							TimerArg.m_ulArg =
508 							    (unsigned long)
509 							    kEplNmtEventTimerBasicEthernet;
510 						}
511 
512 						// read NMT_BootTime_REC.MNWaitNotAct_U32 from OD
513 						ObdSize = sizeof(dwBuffer);
514 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
515 						Ret =
516 						    EplObduReadEntry
517 						    (EPL_MCO_PTR_INSTANCE_PTR_
518 						     0x1F89, 0x01, &dwBuffer,
519 						     &ObdSize);
520 #else
521 						Ret = kEplObdIndexNotExist;
522 #endif
523 						if (Ret != kEplSuccessful) {
524 							break;
525 						}
526 						// convert us into ms
527 						dwBuffer = dwBuffer / 1000;
528 						if (dwBuffer == 0) {	// timer was below one ms
529 							// set one ms
530 							dwBuffer = 1;
531 						}
532 						TimerArg.m_EventSink =
533 						    kEplEventSinkNmtk;
534 						Ret =
535 						    EplTimeruModifyTimerMs
536 						    (&EplNmtuInstance_g.
537 						     m_TimerHdl,
538 						     (unsigned long)dwBuffer,
539 						     TimerArg);
540 						// potential error is forwarded to event queue which generates error event
541 						break;
542 					}
543 
544 					// node processes only async frames
545 				case kEplNmtMsPreOperational1:
546 					{
547 						DWORD dwBuffer = 0;
548 						tEplObdSize ObdSize;
549 						tEplTimerArg TimerArg;
550 
551 						// create timer to switch automatically to PreOp2 if MN identified all mandatory CNs
552 
553 						// read NMT_BootTime_REC.MNWaitPreOp1_U32 from OD
554 						ObdSize = sizeof(dwBuffer);
555 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
556 						Ret =
557 						    EplObduReadEntry
558 						    (EPL_MCO_PTR_INSTANCE_PTR_
559 						     0x1F89, 0x03, &dwBuffer,
560 						     &ObdSize);
561 						if (Ret != kEplSuccessful) {
562 							// ignore error, because this timeout is optional
563 							dwBuffer = 0;
564 						}
565 #endif
566 						if (dwBuffer == 0) {	// delay is deactivated
567 							// immediately post timer event
568 							Ret =
569 							    EplNmtuNmtEvent
570 							    (kEplNmtEventTimerMsPreOp2);
571 							break;
572 						}
573 						// convert us into ms
574 						dwBuffer = dwBuffer / 1000;
575 						if (dwBuffer == 0) {	// timer was below one ms
576 							// set one ms
577 							dwBuffer = 1;
578 						}
579 						TimerArg.m_EventSink =
580 						    kEplEventSinkNmtk;
581 						TimerArg.m_ulArg =
582 						    (unsigned long)
583 						    kEplNmtEventTimerMsPreOp2;
584 						Ret =
585 						    EplTimeruModifyTimerMs
586 						    (&EplNmtuInstance_g.
587 						     m_TimerHdl,
588 						     (unsigned long)dwBuffer,
589 						     TimerArg);
590 						// potential error is forwarded to event queue which generates error event
591 						break;
592 					}
593 
594 					// node processes isochronous and asynchronous frames
595 				case kEplNmtMsPreOperational2:
596 					{
597 						break;
598 					}
599 
600 					// node should be configured und application is ready
601 				case kEplNmtMsReadyToOperate:
602 					{
603 						break;
604 					}
605 
606 					// normal work state
607 				case kEplNmtMsOperational:
608 					{
609 						break;
610 					}
611 
612 					// no EPL cycle
613 					// -> normal ethernet communication
614 				case kEplNmtMsBasicEthernet:
615 					{
616 						break;
617 					}
618 #endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
619 
620 				default:
621 					{
622 						TRACE1
623 						    ("EplNmtuProcess(): unhandled NMT state 0x%X\n",
624 						     pNmtStateChange->
625 						     m_NewNmtState);
626 					}
627 				}
628 			} else if (Ret == kEplReject) {	// application wants to change NMT state itself
629 				// it's OK
630 				Ret = kEplSuccessful;
631 			}
632 
633 			EPL_DBGLVL_NMTU_TRACE0
634 			    ("EplNmtuProcessEvent(): NMT-State-Maschine announce change of NMT State\n");
635 			break;
636 		}
637 
638 	default:
639 		{
640 			Ret = kEplNmtInvalidEvent;
641 		}
642 
643 	}
644 
645 //Exit:
646 	return Ret;
647 }
648 
649 //---------------------------------------------------------------------------
650 //
651 // Function:    EplNmtuRegisterStateChangeCb
652 //
653 // Description: register Callback-function go get informed about a
654 //              NMT-Change-State-Event
655 //
656 //
657 //
658 // Parameters:  pfnEplNmtStateChangeCb_p = functionpointer
659 //
660 //
661 // Returns:     tEplKernel  = errorcode
662 //
663 //
664 // State:
665 //
666 //---------------------------------------------------------------------------
667 EPLDLLEXPORT tEplKernel PUBLIC
EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback pfnEplNmtStateChangeCb_p)668 EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback
669 			     pfnEplNmtStateChangeCb_p)
670 {
671 	tEplKernel Ret;
672 
673 	Ret = kEplSuccessful;
674 
675 	// save callback-function in modul global var
676 	EplNmtuInstance_g.m_pfnNmtChangeCb = pfnEplNmtStateChangeCb_p;
677 
678 	return Ret;
679 
680 }
681 
682 //=========================================================================//
683 //                                                                         //
684 //          P R I V A T E   F U N C T I O N S                              //
685 //                                                                         //
686 //=========================================================================//
687 
688 //---------------------------------------------------------------------------
689 //
690 // Function:
691 //
692 // Description:
693 //
694 //
695 //
696 // Parameters:
697 //
698 //
699 // Returns:
700 //
701 //
702 // State:
703 //
704 //---------------------------------------------------------------------------
705 
706 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
707 
708 // EOF
709