1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: source file for kernel DLL module
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
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.
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.
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.
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.
50 -------------------------------------------------------------------------
52 $RCSfile: EplDllk.c,v $
56 $Revision: 1.21 $ $Date: 2008/11/13 17:13:09 $
63 -------------------------------------------------------------------------
67 2006/06/12 d.k.: start of the implementation, version 1.00
69 ****************************************************************************/
71 #include "kernel/EplDllk.h"
72 #include "kernel/EplDllkCal.h"
73 #include "kernel/EplEventk.h"
74 #include "kernel/EplNmtk.h"
76 #include "Benchmark.h"
78 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
79 #include "kernel/EplPdok.h"
82 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
83 #include "kernel/VirtualEthernet.h"
86 //#if EPL_TIMER_USE_HIGHRES != FALSE
87 #include "kernel/EplTimerHighResk.h"
90 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
92 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0)
93 #error "EPL module DLLK needs EPL module NMTK!"
96 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) && (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
97 #error "EPL module DLLK: select only one of EPL_DLL_PRES_READY_AFTER_SOA and EPL_DLL_PRES_READY_AFTER_SOC."
100 #if ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) \
101 && (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
102 #error "EPL module DLLK: currently, EPL_DLL_PRES_READY_AFTER_* is not supported if EPL_MODULE_NMT_MN is enabled."
105 #if (EDRV_FAST_TXFRAMES == FALSE) && \
106 ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE))
107 #error "EPL module DLLK: EPL_DLL_PRES_READY_AFTER_* is enabled, but not EDRV_FAST_TXFRAMES."
110 /***************************************************************************/
113 /* G L O B A L D E F I N I T I O N S */
116 /***************************************************************************/
118 //---------------------------------------------------------------------------
120 //---------------------------------------------------------------------------
122 // TracePoint support for realtime-debugging
123 #ifdef _DBG_TRACE_POINTS_
124 void PUBLIC
TgtDbgSignalTracePoint(BYTE bTracePointNumber_p
);
125 void PUBLIC
TgtDbgPostTraceValue(DWORD dwTraceValue_p
);
126 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
127 #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
129 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
130 #define TGT_DBG_POST_TRACE_VALUE(v)
132 #define EPL_DLLK_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
133 TGT_DBG_POST_TRACE_VALUE((kEplEventSinkDllk << 28) | (Event_p << 24) \
134 | (uiNodeId_p << 16) | wErrorCode_p)
136 /***************************************************************************/
139 /* C L A S S EplDllk */
142 /***************************************************************************/
147 /***************************************************************************/
149 //=========================================================================//
151 // P R I V A T E D E F I N I T I O N S //
153 //=========================================================================//
155 //---------------------------------------------------------------------------
157 //---------------------------------------------------------------------------
159 // defines for indexes of tEplDllInstance.m_pTxFrameInfo
160 #define EPL_DLLK_TXFRAME_IDENTRES 0 // IdentResponse on CN / MN
161 #define EPL_DLLK_TXFRAME_STATUSRES 1 // StatusResponse on CN / MN
162 #define EPL_DLLK_TXFRAME_NMTREQ 2 // NMT Request from FIFO on CN / MN
163 #define EPL_DLLK_TXFRAME_NONEPL 3 // non-EPL frame from FIFO on CN / MN
164 #define EPL_DLLK_TXFRAME_PRES 4 // PRes on CN / MN
165 #define EPL_DLLK_TXFRAME_SOC 5 // SoC on MN
166 #define EPL_DLLK_TXFRAME_SOA 6 // SoA on MN
167 #define EPL_DLLK_TXFRAME_PREQ 7 // PReq on MN
168 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
169 #define EPL_DLLK_TXFRAME_COUNT (7 + EPL_D_NMT_MaxCNNumber_U8 + 2) // on MN: 7 + MaxPReq of regular CNs + 1 Diag + 1 Router
171 #define EPL_DLLK_TXFRAME_COUNT 5 // on CN: 5
174 #define EPL_DLLK_BUFLEN_EMPTY 0 // buffer is empty
175 #define EPL_DLLK_BUFLEN_FILLING 1 // just the buffer is being filled
176 #define EPL_DLLK_BUFLEN_MIN 60 // minimum ethernet frame length
178 //---------------------------------------------------------------------------
180 //---------------------------------------------------------------------------
183 kEplDllGsInit
= 0x00, // MN/CN: initialisation (< PreOp2)
184 kEplDllCsWaitPreq
= 0x01, // CN: wait for PReq frame
185 kEplDllCsWaitSoc
= 0x02, // CN: wait for SoC frame
186 kEplDllCsWaitSoa
= 0x03, // CN: wait for SoA frame
187 kEplDllMsNonCyclic
= 0x04, // MN: reduced EPL cycle (PreOp1)
188 kEplDllMsWaitSocTrig
= 0x05, // MN: wait for SoC trigger (cycle timer)
189 kEplDllMsWaitPreqTrig
= 0x06, // MN: wait for (first) PReq trigger (WaitSoCPReq_U32)
190 kEplDllMsWaitPres
= 0x07, // MN: wait for PRes frame from CN
191 kEplDllMsWaitSoaTrig
= 0x08, // MN: wait for SoA trigger (PRes transmitted)
192 kEplDllMsWaitAsndTrig
= 0x09, // MN: wait for ASnd trigger (SoA transmitted)
193 kEplDllMsWaitAsnd
= 0x0A, // MN: wait for ASnd frame if SoA contained invitation
198 BYTE m_be_abSrcMac
[6];
199 tEdrvTxBuffer
*m_pTxBuffer
; // Buffers for Tx-Frames
200 unsigned int m_uiMaxTxFrames
;
201 BYTE m_bFlag1
; // Flag 1 with EN, EC for PRes, StatusRes
202 BYTE m_bMnFlag1
; // Flag 1 with EA, ER from PReq, SoA of MN
203 BYTE m_bFlag2
; // Flag 2 with PR and RS for PRes, StatusRes, IdentRes
204 tEplDllConfigParam m_DllConfigParam
;
205 tEplDllIdentParam m_DllIdentParam
;
206 tEplDllState m_DllState
;
207 tEplDllkCbAsync m_pfnCbAsync
;
208 tEplDllAsndFilter m_aAsndFilter
[EPL_DLL_MAX_ASND_SERVICE_ID
];
210 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
211 tEplDllkNodeInfo
*m_pFirstNodeInfo
;
212 tEplDllkNodeInfo
*m_pCurNodeInfo
;
213 tEplDllkNodeInfo m_aNodeInfo
[EPL_NMT_MAX_NODE_ID
];
214 tEplDllReqServiceId m_LastReqServiceId
;
215 unsigned int m_uiLastTargetNodeId
;
218 #if EPL_TIMER_USE_HIGHRES != FALSE
219 tEplTimerHdl m_TimerHdlCycle
; // used for EPL cycle monitoring on CN and generation on MN
220 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
221 tEplTimerHdl m_TimerHdlResponse
; // used for CN response monitoring
222 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
225 unsigned int m_uiCycleCount
; // cycle counter (needed for multiplexed cycle support)
226 unsigned long long m_ullFrameTimeout
; // frame timeout (cycle length + loss of frame tolerance)
230 //---------------------------------------------------------------------------
232 //---------------------------------------------------------------------------
234 // if no dynamic memory allocation shall be used
235 // define structures statically
236 static tEplDllkInstance EplDllkInstance_g
;
238 static tEdrvTxBuffer aEplDllkTxBuffer_l
[EPL_DLLK_TXFRAME_COUNT
];
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
244 // change DLL state on event
245 static tEplKernel
EplDllkChangeState(tEplNmtEvent NmtEvent_p
,
246 tEplNmtState NmtState_p
);
248 // called from EdrvInterruptHandler()
249 static void EplDllkCbFrameReceived(tEdrvRxBuffer
* pRxBuffer_p
);
251 // called from EdrvInterruptHandler()
252 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer
* pTxBuffer_p
);
254 // check frame and set missing information
255 static tEplKernel
EplDllkCheckFrame(tEplFrame
* pFrame_p
,
256 unsigned int uiFrameSize_p
);
258 // called by high resolution timer module to monitor EPL cycle as CN
259 #if EPL_TIMER_USE_HIGHRES != FALSE
260 static tEplKernel PUBLIC
EplDllkCbCnTimer(tEplTimerEventArg
* pEventArg_p
);
263 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
264 // MN: returns internal node info structure
265 static tEplDllkNodeInfo
*EplDllkGetNodeInfo(unsigned int uiNodeId_p
);
268 static tEplKernel
EplDllkMnSendSoa(tEplNmtState NmtState_p
,
269 tEplDllState
* pDllStateProposed_p
,
270 BOOL fEnableInvitation_p
);
272 static tEplKernel
EplDllkMnSendSoc(void);
274 static tEplKernel
EplDllkMnSendPreq(tEplNmtState NmtState_p
,
275 tEplDllState
* pDllStateProposed_p
);
277 static tEplKernel
EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
279 unsigned int uiNodeId_p
);
281 static tEplKernel PUBLIC
EplDllkCbMnTimerCycle(tEplTimerEventArg
* pEventArg_p
);
283 static tEplKernel PUBLIC
EplDllkCbMnTimerResponse(tEplTimerEventArg
*
288 //=========================================================================//
290 // P U B L I C F U N C T I O N S //
292 //=========================================================================//
294 //---------------------------------------------------------------------------
296 // Function: EplDllkAddInstance()
298 // Description: add and initialize new instance of EPL stack
300 // Parameters: pInitParam_p = initialisation parameters like MAC address
302 // Returns: tEplKernel = error code
307 //---------------------------------------------------------------------------
309 tEplKernel
EplDllkAddInstance(tEplDllkInitParam
* pInitParam_p
)
311 tEplKernel Ret
= kEplSuccessful
;
312 unsigned int uiIndex
;
313 tEdrvInitParam EdrvInitParam
;
315 // reset instance structure
316 EPL_MEMSET(&EplDllkInstance_g
, 0, sizeof(EplDllkInstance_g
));
318 #if EPL_TIMER_USE_HIGHRES != FALSE
319 Ret
= EplTimerHighReskInit();
320 if (Ret
!= kEplSuccessful
) { // error occured while initializing high resolution timer module
325 // if dynamic memory allocation available
326 // allocate instance structure
327 // allocate TPDO and RPDO table with default size
329 // initialize and link pointers in instance structure to frame tables
330 EplDllkInstance_g
.m_pTxBuffer
= aEplDllkTxBuffer_l
;
331 EplDllkInstance_g
.m_uiMaxTxFrames
=
332 sizeof(aEplDllkTxBuffer_l
) / sizeof(tEdrvTxBuffer
);
335 EplDllkInstance_g
.m_DllState
= kEplDllGsInit
;
337 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
338 // set up node info structure
339 for (uiIndex
= 0; uiIndex
< tabentries(EplDllkInstance_g
.m_aNodeInfo
);
341 EplDllkInstance_g
.m_aNodeInfo
[uiIndex
].m_uiNodeId
= uiIndex
+ 1;
342 EplDllkInstance_g
.m_aNodeInfo
[uiIndex
].m_wPresPayloadLimit
=
348 EPL_MEMCPY(EdrvInitParam
.m_abMyMacAddr
, pInitParam_p
->m_be_abSrcMac
, 6);
349 EdrvInitParam
.m_pfnRxHandler
= EplDllkCbFrameReceived
;
350 EdrvInitParam
.m_pfnTxHandler
= EplDllkCbFrameTransmitted
;
351 Ret
= EdrvInit(&EdrvInitParam
);
352 if (Ret
!= kEplSuccessful
) { // error occured while initializing ethernet driver
355 // copy local MAC address from Ethernet driver back to local instance structure
356 // because Ethernet driver may have read it from controller EEPROM
357 EPL_MEMCPY(EplDllkInstance_g
.m_be_abSrcMac
, EdrvInitParam
.m_abMyMacAddr
,
359 EPL_MEMCPY(pInitParam_p
->m_be_abSrcMac
, EdrvInitParam
.m_abMyMacAddr
, 6);
361 // initialize TxBuffer array
362 for (uiIndex
= 0; uiIndex
< EplDllkInstance_g
.m_uiMaxTxFrames
;
364 EplDllkInstance_g
.m_pTxBuffer
[uiIndex
].m_pbBuffer
= NULL
;
367 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
368 Ret
= VEthAddInstance(pInitParam_p
);
375 //---------------------------------------------------------------------------
377 // Function: EplDllkDelInstance()
379 // Description: deletes an instance of EPL stack
381 // Parameters: (none)
383 // Returns: tEplKernel = error code
388 //---------------------------------------------------------------------------
390 tEplKernel
EplDllkDelInstance(void)
392 tEplKernel Ret
= kEplSuccessful
;
395 EplDllkInstance_g
.m_DllState
= kEplDllGsInit
;
397 #if EPL_TIMER_USE_HIGHRES != FALSE
398 Ret
= EplTimerHighReskDelInstance();
401 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
402 Ret
= VEthDelInstance();
405 Ret
= EdrvShutdown();
409 //---------------------------------------------------------------------------
411 // Function: EplDllkCreateTxFrame
413 // Description: creates the buffer for a Tx frame and registers it to the
416 // Parameters: puiHandle_p = OUT: handle to frame buffer
417 // ppFrame_p = OUT: pointer to pointer of EPL frame
418 // puiFrameSize_p = IN/OUT: pointer to size of frame
419 // returned size is always equal or larger than
420 // requested size, if that is not possible
421 // an error will be returned
422 // MsgType_p = EPL message type
423 // ServiceId_p = Service ID in case of ASnd frame, otherwise
424 // kEplDllAsndNotDefined
426 // Returns: tEplKernel = error code
431 //---------------------------------------------------------------------------
433 tEplKernel
EplDllkCreateTxFrame(unsigned int *puiHandle_p
,
434 tEplFrame
** ppFrame_p
,
435 unsigned int *puiFrameSize_p
,
436 tEplMsgType MsgType_p
,
437 tEplDllAsndServiceId ServiceId_p
)
439 tEplKernel Ret
= kEplSuccessful
;
441 unsigned int uiHandle
= EplDllkInstance_g
.m_uiMaxTxFrames
;
442 tEdrvTxBuffer
*pTxBuffer
= NULL
;
444 if (MsgType_p
== kEplMsgTypeAsnd
) {
445 // search for fixed Tx buffers
446 if (ServiceId_p
== kEplDllAsndIdentResponse
) {
447 uiHandle
= EPL_DLLK_TXFRAME_IDENTRES
;
448 } else if (ServiceId_p
== kEplDllAsndStatusResponse
) {
449 uiHandle
= EPL_DLLK_TXFRAME_STATUSRES
;
450 } else if ((ServiceId_p
== kEplDllAsndNmtRequest
)
451 || (ServiceId_p
== kEplDllAsndNmtCommand
)) {
452 uiHandle
= EPL_DLLK_TXFRAME_NMTREQ
;
455 if (uiHandle
>= EplDllkInstance_g
.m_uiMaxTxFrames
) { // look for free entry
456 uiHandle
= EPL_DLLK_TXFRAME_PREQ
;
457 pTxBuffer
= &EplDllkInstance_g
.m_pTxBuffer
[uiHandle
];
458 for (; uiHandle
< EplDllkInstance_g
.m_uiMaxTxFrames
;
459 uiHandle
++, pTxBuffer
++) {
460 if (pTxBuffer
->m_pbBuffer
== NULL
) { // free entry found
465 } else if (MsgType_p
== kEplMsgTypeNonEpl
) {
466 uiHandle
= EPL_DLLK_TXFRAME_NONEPL
;
467 } else if (MsgType_p
== kEplMsgTypePres
) {
468 uiHandle
= EPL_DLLK_TXFRAME_PRES
;
469 } else if (MsgType_p
== kEplMsgTypeSoc
) {
470 uiHandle
= EPL_DLLK_TXFRAME_SOC
;
471 } else if (MsgType_p
== kEplMsgTypeSoa
) {
472 uiHandle
= EPL_DLLK_TXFRAME_SOA
;
473 } else { // look for free entry
474 uiHandle
= EPL_DLLK_TXFRAME_PREQ
;
475 pTxBuffer
= &EplDllkInstance_g
.m_pTxBuffer
[uiHandle
];
476 for (; uiHandle
< EplDllkInstance_g
.m_uiMaxTxFrames
;
477 uiHandle
++, pTxBuffer
++) {
478 if (pTxBuffer
->m_pbBuffer
== NULL
) { // free entry found
482 if (pTxBuffer
->m_pbBuffer
!= NULL
) {
483 Ret
= kEplEdrvNoFreeBufEntry
;
488 // test if requested entry is free
489 pTxBuffer
= &EplDllkInstance_g
.m_pTxBuffer
[uiHandle
];
490 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // entry is not free
491 Ret
= kEplEdrvNoFreeBufEntry
;
495 pTxBuffer
->m_EplMsgType
= MsgType_p
;
496 pTxBuffer
->m_uiMaxBufferLen
= *puiFrameSize_p
;
498 Ret
= EdrvAllocTxMsgBuffer(pTxBuffer
);
499 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
502 // because buffer size may be larger than requested
503 // memorize real length of frame
504 pTxBuffer
->m_uiTxMsgLen
= *puiFrameSize_p
;
506 // fill whole frame with 0
507 EPL_MEMSET(pTxBuffer
->m_pbBuffer
, 0, pTxBuffer
->m_uiMaxBufferLen
);
509 pTxFrame
= (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
511 if (MsgType_p
!= kEplMsgTypeNonEpl
) { // fill out Frame only if it is an EPL frame
513 AmiSetWordToBe(&pTxFrame
->m_be_wEtherType
,
514 EPL_C_DLL_ETHERTYPE_EPL
);
516 AmiSetByteToLe(&pTxFrame
->m_le_bSrcNodeId
,
517 (BYTE
) EplDllkInstance_g
.m_DllConfigParam
.
519 // source MAC address
520 EPL_MEMCPY(&pTxFrame
->m_be_abSrcMac
[0],
521 &EplDllkInstance_g
.m_be_abSrcMac
[0], 6);
523 case kEplMsgTypeAsnd
:
524 // destination MAC address
525 AmiSetQword48ToBe(&pTxFrame
->m_be_abDstMac
[0],
526 EPL_C_DLL_MULTICAST_ASND
);
527 // destination node ID
528 switch (ServiceId_p
) {
529 case kEplDllAsndIdentResponse
:
530 case kEplDllAsndStatusResponse
:
531 { // IdentResponses and StatusResponses are Broadcast
532 AmiSetByteToLe(&pTxFrame
->
535 EPL_C_ADR_BROADCAST
);
543 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.m_le_bServiceId
,
548 // destination MAC address
549 AmiSetQword48ToBe(&pTxFrame
->m_be_abDstMac
[0],
550 EPL_C_DLL_MULTICAST_SOC
);
551 // destination node ID
552 AmiSetByteToLe(&pTxFrame
->m_le_bDstNodeId
,
553 (BYTE
) EPL_C_ADR_BROADCAST
);
555 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (BYTE) 0);
556 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (BYTE) 0);
560 // destination MAC address
561 AmiSetQword48ToBe(&pTxFrame
->m_be_abDstMac
[0],
562 EPL_C_DLL_MULTICAST_SOA
);
563 // destination node ID
564 AmiSetByteToLe(&pTxFrame
->m_le_bDstNodeId
,
565 (BYTE
) EPL_C_ADR_BROADCAST
);
567 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (BYTE) 0);
568 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (BYTE) 0);
569 // EPL profile version
570 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.m_le_bEplVersion
,
571 (BYTE
) EPL_SPEC_VERSION
);
574 case kEplMsgTypePres
:
575 // destination MAC address
576 AmiSetQword48ToBe(&pTxFrame
->m_be_abDstMac
[0],
577 EPL_C_DLL_MULTICAST_PRES
);
578 // destination node ID
579 AmiSetByteToLe(&pTxFrame
->m_le_bDstNodeId
,
580 (BYTE
) EPL_C_ADR_BROADCAST
);
582 //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (BYTE) 0);
583 //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (BYTE) 0);
585 //AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0);
588 case kEplMsgTypePreq
:
590 //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (BYTE) 0);
591 //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (BYTE) 0);
593 //AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0);
600 AmiSetByteToLe(&pTxFrame
->m_le_bMessageType
, (BYTE
) MsgType_p
);
603 *ppFrame_p
= pTxFrame
;
604 *puiFrameSize_p
= pTxBuffer
->m_uiMaxBufferLen
;
605 *puiHandle_p
= uiHandle
;
611 //---------------------------------------------------------------------------
613 // Function: EplDllkDeleteTxFrame
615 // Description: deletes the buffer for a Tx frame and frees it in the
618 // Parameters: uiHandle_p = IN: handle to frame buffer
620 // Returns: tEplKernel = error code
625 //---------------------------------------------------------------------------
627 tEplKernel
EplDllkDeleteTxFrame(unsigned int uiHandle_p
)
629 tEplKernel Ret
= kEplSuccessful
;
630 tEdrvTxBuffer
*pTxBuffer
= NULL
;
632 if (uiHandle_p
>= EplDllkInstance_g
.m_uiMaxTxFrames
) { // handle is not valid
633 Ret
= kEplDllIllegalHdl
;
637 pTxBuffer
= &EplDllkInstance_g
.m_pTxBuffer
[uiHandle_p
];
639 // mark buffer as free so that frame will not be send in future anymore
640 // $$$ d.k. What's up with running transmissions?
641 pTxBuffer
->m_uiTxMsgLen
= EPL_DLLK_BUFLEN_EMPTY
;
642 pTxBuffer
->m_pbBuffer
= NULL
;
645 Ret
= EdrvReleaseTxMsgBuffer(pTxBuffer
);
646 if (Ret
!= kEplSuccessful
) { // error occured while releasing Tx frame
654 //---------------------------------------------------------------------------
656 // Function: EplDllkProcess
658 // Description: process the passed event
660 // Parameters: pEvent_p = event to be processed
662 // Returns: tEplKernel = error code
667 //---------------------------------------------------------------------------
669 tEplKernel
EplDllkProcess(tEplEvent
* pEvent_p
)
671 tEplKernel Ret
= kEplSuccessful
;
673 tEdrvTxBuffer
*pTxBuffer
;
674 unsigned int uiHandle
;
675 unsigned int uiFrameSize
;
676 BYTE abMulticastMac
[6];
677 tEplDllAsyncReqPriority AsyncReqPriority
;
678 unsigned int uiFrameCount
;
679 tEplNmtState NmtState
;
680 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
681 tEplFrameInfo FrameInfo
;
684 switch (pEvent_p
->m_EventType
) {
685 case kEplEventTypeDllkCreate
:
687 // $$$ reset ethernet driver
689 NmtState
= *((tEplNmtState
*) pEvent_p
->m_pArg
);
691 // initialize flags for PRes and StatusRes
692 EplDllkInstance_g
.m_bFlag1
= EPL_FRAME_FLAG1_EC
;
693 EplDllkInstance_g
.m_bMnFlag1
= 0;
694 EplDllkInstance_g
.m_bFlag2
= 0;
696 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
697 // initialize linked node list
698 EplDllkInstance_g
.m_pFirstNodeInfo
= NULL
;
701 // register TxFrames in Edrv
704 uiFrameSize
= EPL_C_DLL_MINSIZE_IDENTRES
;
706 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
707 &uiFrameSize
, kEplMsgTypeAsnd
,
708 kEplDllAsndIdentResponse
);
709 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
712 // EPL profile version
713 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
714 m_IdentResponse
.m_le_bEplProfileVersion
,
715 (BYTE
) EPL_SPEC_VERSION
);
717 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
718 m_IdentResponse
.m_le_dwFeatureFlags
,
719 EplDllkInstance_g
.m_DllConfigParam
.
722 AmiSetWordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
723 m_IdentResponse
.m_le_wMtu
,
724 (WORD
) EplDllkInstance_g
.
725 m_DllConfigParam
.m_uiAsyncMtu
);
727 AmiSetWordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
728 m_IdentResponse
.m_le_wPollInSize
,
729 (WORD
) EplDllkInstance_g
.
731 m_uiPreqActPayloadLimit
);
733 AmiSetWordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
734 m_IdentResponse
.m_le_wPollOutSize
,
735 (WORD
) EplDllkInstance_g
.
737 m_uiPresActPayloadLimit
);
738 // ResponseTime / PresMaxLatency
739 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
740 m_IdentResponse
.m_le_dwResponseTime
,
741 EplDllkInstance_g
.m_DllConfigParam
.
744 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
745 m_IdentResponse
.m_le_dwDeviceType
,
746 EplDllkInstance_g
.m_DllIdentParam
.
749 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
750 m_IdentResponse
.m_le_dwVendorId
,
751 EplDllkInstance_g
.m_DllIdentParam
.
754 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
755 m_IdentResponse
.m_le_dwProductCode
,
756 EplDllkInstance_g
.m_DllIdentParam
.
759 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
760 m_IdentResponse
.m_le_dwRevisionNumber
,
761 EplDllkInstance_g
.m_DllIdentParam
.
764 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
765 m_IdentResponse
.m_le_dwSerialNumber
,
766 EplDllkInstance_g
.m_DllIdentParam
.
768 // VendorSpecificExt1
769 AmiSetQword64ToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
771 m_le_qwVendorSpecificExt1
,
772 EplDllkInstance_g
.m_DllIdentParam
.
773 m_qwVendorSpecificExt1
);
774 // VerifyConfigurationDate
775 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
777 m_le_dwVerifyConfigurationDate
,
778 EplDllkInstance_g
.m_DllIdentParam
.
779 m_dwVerifyConfigurationDate
);
780 // VerifyConfigurationTime
781 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
783 m_le_dwVerifyConfigurationTime
,
784 EplDllkInstance_g
.m_DllIdentParam
.
785 m_dwVerifyConfigurationTime
);
787 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
789 m_le_dwApplicationSwDate
,
790 EplDllkInstance_g
.m_DllIdentParam
.
791 m_dwApplicationSwDate
);
793 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
795 m_le_dwApplicationSwTime
,
796 EplDllkInstance_g
.m_DllIdentParam
.
797 m_dwApplicationSwTime
);
799 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
800 m_IdentResponse
.m_le_dwIpAddress
,
801 EplDllkInstance_g
.m_DllIdentParam
.
804 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
805 m_IdentResponse
.m_le_dwSubnetMask
,
806 EplDllkInstance_g
.m_DllIdentParam
.
809 AmiSetDwordToLe(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
810 m_IdentResponse
.m_le_dwDefaultGateway
,
811 EplDllkInstance_g
.m_DllIdentParam
.
814 EPL_MEMCPY(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
815 m_IdentResponse
.m_le_sHostname
[0],
816 &EplDllkInstance_g
.m_DllIdentParam
.
818 sizeof(EplDllkInstance_g
.m_DllIdentParam
.
820 // VendorSpecificExt2
821 EPL_MEMCPY(&pTxFrame
->m_Data
.m_Asnd
.m_Payload
.
822 m_IdentResponse
.m_le_abVendorSpecificExt2
[0],
823 &EplDllkInstance_g
.m_DllIdentParam
.
824 m_abVendorSpecificExt2
[0],
825 sizeof(EplDllkInstance_g
.m_DllIdentParam
.
826 m_abVendorSpecificExt2
));
829 uiFrameSize
= EPL_C_DLL_MINSIZE_STATUSRES
;
831 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
832 &uiFrameSize
, kEplMsgTypeAsnd
,
833 kEplDllAsndStatusResponse
);
834 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
837 // PRes $$$ maybe move this to PDO module
838 if ((EplDllkInstance_g
.m_DllConfigParam
.m_fAsyncOnly
==
840 && (EplDllkInstance_g
.m_DllConfigParam
.m_uiPresActPayloadLimit
>= 36)) { // it is not configured as async-only CN,
841 // so take part in isochronous phase and register PRes frame
843 EplDllkInstance_g
.m_DllConfigParam
.
844 m_uiPresActPayloadLimit
+ 24;
846 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
849 kEplDllAsndNotDefined
);
850 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
853 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
854 // initially encode TPDO -> inform PDO module
855 FrameInfo
.m_pFrame
= pTxFrame
;
856 FrameInfo
.m_uiFrameSize
= uiFrameSize
;
857 Ret
= EplPdokCbPdoTransmitted(&FrameInfo
);
859 // reset cycle counter
860 EplDllkInstance_g
.m_uiCycleCount
= 0;
861 } else { // it is an async-only CN
862 // fool EplDllkChangeState() to think that PRes was not expected
863 EplDllkInstance_g
.m_uiCycleCount
= 1;
867 uiFrameSize
= EPL_C_IP_MAX_MTU
;
869 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
870 &uiFrameSize
, kEplMsgTypeAsnd
,
871 kEplDllAsndNmtRequest
);
872 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
875 // mark Tx buffer as empty
876 EplDllkInstance_g
.m_pTxBuffer
[uiHandle
].m_uiTxMsgLen
=
877 EPL_DLLK_BUFLEN_EMPTY
;
880 uiFrameSize
= EPL_C_IP_MAX_MTU
;
882 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
885 kEplDllAsndNotDefined
);
886 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
889 // mark Tx buffer as empty
890 EplDllkInstance_g
.m_pTxBuffer
[uiHandle
].m_uiTxMsgLen
=
891 EPL_DLLK_BUFLEN_EMPTY
;
893 // register multicast MACs in ethernet driver
894 AmiSetQword48ToBe(&abMulticastMac
[0],
895 EPL_C_DLL_MULTICAST_SOC
);
896 Ret
= EdrvDefineRxMacAddrEntry(abMulticastMac
);
897 AmiSetQword48ToBe(&abMulticastMac
[0],
898 EPL_C_DLL_MULTICAST_SOA
);
899 Ret
= EdrvDefineRxMacAddrEntry(abMulticastMac
);
900 AmiSetQword48ToBe(&abMulticastMac
[0],
901 EPL_C_DLL_MULTICAST_PRES
);
902 Ret
= EdrvDefineRxMacAddrEntry(abMulticastMac
);
903 AmiSetQword48ToBe(&abMulticastMac
[0],
904 EPL_C_DLL_MULTICAST_ASND
);
905 Ret
= EdrvDefineRxMacAddrEntry(abMulticastMac
);
907 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
908 if (NmtState
>= kEplNmtMsNotActive
) { // local node is MN
909 unsigned int uiIndex
;
912 uiFrameSize
= EPL_C_DLL_MINSIZE_SOC
;
914 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
917 kEplDllAsndNotDefined
);
918 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
922 uiFrameSize
= EPL_C_DLL_MINSIZE_SOA
;
924 EplDllkCreateTxFrame(&uiHandle
, &pTxFrame
,
927 kEplDllAsndNotDefined
);
928 if (Ret
!= kEplSuccessful
) { // error occured while registering Tx frame
934 tabentries(EplDllkInstance_g
.m_aNodeInfo
);
936 // EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
937 EplDllkInstance_g
.m_aNodeInfo
[uiIndex
].
938 m_wPresPayloadLimit
=
939 (WORD
) EplDllkInstance_g
.
941 m_uiIsochrRxMaxPayload
;
944 // calculate cycle length
945 EplDllkInstance_g
.m_ullFrameTimeout
= 1000LL
947 ((unsigned long long)EplDllkInstance_g
.
948 m_DllConfigParam
.m_dwCycleLen
);
950 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
952 Ret
= EplDllkCalAsyncClearBuffer();
957 case kEplEventTypeDllkDestroy
:
959 // destroy all data structures
961 NmtState
= *((tEplNmtState
*) pEvent_p
->m_pArg
);
964 Ret
= EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES
);
965 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
969 Ret
= EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES
);
970 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
974 Ret
= EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES
);
975 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
979 Ret
= EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ
);
980 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
984 Ret
= EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL
);
985 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
988 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
989 if (NmtState
>= kEplNmtMsNotActive
) { // local node was MN
990 unsigned int uiIndex
;
993 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC
);
994 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
999 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA
);
1000 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
1006 tabentries(EplDllkInstance_g
.m_aNodeInfo
);
1008 if (EplDllkInstance_g
.
1009 m_aNodeInfo
[uiIndex
].
1010 m_pPreqTxBuffer
!= NULL
) {
1013 m_aNodeInfo
[uiIndex
].
1018 m_aNodeInfo
[uiIndex
].
1019 m_pPreqTxBuffer
= NULL
;
1021 EplDllkDeleteTxFrame
1023 if (Ret
!= kEplSuccessful
) { // error occured while deregistering Tx frame
1028 EplDllkInstance_g
.m_aNodeInfo
[uiIndex
].
1029 m_wPresPayloadLimit
= 0xFFFF;
1032 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1034 // deregister multicast MACs in ethernet driver
1035 AmiSetQword48ToBe(&abMulticastMac
[0],
1036 EPL_C_DLL_MULTICAST_SOC
);
1037 Ret
= EdrvUndefineRxMacAddrEntry(abMulticastMac
);
1038 AmiSetQword48ToBe(&abMulticastMac
[0],
1039 EPL_C_DLL_MULTICAST_SOA
);
1040 Ret
= EdrvUndefineRxMacAddrEntry(abMulticastMac
);
1041 AmiSetQword48ToBe(&abMulticastMac
[0],
1042 EPL_C_DLL_MULTICAST_PRES
);
1043 Ret
= EdrvUndefineRxMacAddrEntry(abMulticastMac
);
1044 AmiSetQword48ToBe(&abMulticastMac
[0],
1045 EPL_C_DLL_MULTICAST_ASND
);
1046 Ret
= EdrvUndefineRxMacAddrEntry(abMulticastMac
);
1049 #if EPL_TIMER_USE_HIGHRES != FALSE
1051 EplTimerHighReskDeleteTimer(&EplDllkInstance_g
.
1058 case kEplEventTypeDllkFillTx
:
1060 // fill TxBuffer of specified priority with new frame if empty
1064 *((tEplDllAsyncReqPriority
*) pEvent_p
->m_pArg
);
1065 switch (AsyncReqPriority
) {
1066 case kEplDllAsyncReqPrioNmt
: // NMT request priority
1071 [EPL_DLLK_TXFRAME_NMTREQ
];
1072 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // NmtRequest does exist
1073 // check if frame is empty and not being filled
1074 if (pTxBuffer
->m_uiTxMsgLen
==
1075 EPL_DLLK_BUFLEN_EMPTY
) {
1076 // mark Tx buffer as filling is in process
1079 EPL_DLLK_BUFLEN_FILLING
;
1080 // set max buffer size as input parameter
1084 // copy frame from shared loop buffer to Tx buffer
1086 EplDllkCalAsyncGetTxFrame
1108 } else if (Ret
== kEplDllAsyncTxBufferEmpty
) { // empty Tx buffer is not a real problem
1109 // so just ignore it
1112 // mark Tx buffer as empty
1116 EPL_DLLK_BUFLEN_EMPTY
;
1123 default: // generic priority
1128 [EPL_DLLK_TXFRAME_NONEPL
];
1129 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // non-EPL frame does exist
1130 // check if frame is empty and not being filled
1131 if (pTxBuffer
->m_uiTxMsgLen
==
1132 EPL_DLLK_BUFLEN_EMPTY
) {
1133 // mark Tx buffer as filling is in process
1136 EPL_DLLK_BUFLEN_FILLING
;
1137 // set max buffer size as input parameter
1141 // copy frame from shared loop buffer to Tx buffer
1143 EplDllkCalAsyncGetTxFrame
1165 } else if (Ret
== kEplDllAsyncTxBufferEmpty
) { // empty Tx buffer is not a real problem
1166 // so just ignore it
1169 // mark Tx buffer as empty
1173 EPL_DLLK_BUFLEN_EMPTY
;
1181 NmtState
= EplNmtkGetNmtState();
1183 if ((NmtState
== kEplNmtCsBasicEthernet
) || (NmtState
== kEplNmtMsBasicEthernet
)) { // send frame immediately
1184 if (pTxFrame
!= NULL
) { // frame is present
1185 // padding is done by Edrv or ethernet controller
1186 Ret
= EdrvSendTxMsg(pTxBuffer
);
1187 } else { // no frame moved to TxBuffer
1188 // check if TxBuffers contain unsent frames
1189 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NMTREQ
].m_uiTxMsgLen
> EPL_DLLK_BUFLEN_EMPTY
) { // NMT request Tx buffer contains a frame
1192 (&EplDllkInstance_g
.
1194 [EPL_DLLK_TXFRAME_NMTREQ
]);
1195 } else if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NONEPL
].m_uiTxMsgLen
> EPL_DLLK_BUFLEN_EMPTY
) { // non-EPL Tx buffer contains a frame
1198 (&EplDllkInstance_g
.
1200 [EPL_DLLK_TXFRAME_NONEPL
]);
1202 if (Ret
== kEplInvalidOperation
) { // ignore error if caused by already active transmission
1203 Ret
= kEplSuccessful
;
1206 // reset PRes flag 2
1207 EplDllkInstance_g
.m_bFlag2
= 0;
1209 // update Flag 2 (PR, RS)
1211 EplDllkCalAsyncGetTxCount(&AsyncReqPriority
,
1213 if (AsyncReqPriority
== kEplDllAsyncReqPrioNmt
) { // non-empty FIFO with hightest priority is for NMT requests
1214 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NMTREQ
].m_uiTxMsgLen
> EPL_DLLK_BUFLEN_EMPTY
) { // NMT request Tx buffer contains a frame
1215 // add one more frame
1218 } else { // non-empty FIFO with highest priority is for generic frames
1219 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NMTREQ
].m_uiTxMsgLen
> EPL_DLLK_BUFLEN_EMPTY
) { // NMT request Tx buffer contains a frame
1220 // use NMT request FIFO, because of higher priority
1223 kEplDllAsyncReqPrioNmt
;
1224 } else if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NONEPL
].m_uiTxMsgLen
> EPL_DLLK_BUFLEN_EMPTY
) { // non-EPL Tx buffer contains a frame
1225 // use NMT request FIFO, because of higher priority
1226 // add one more frame
1231 if (uiFrameCount
> 7) { // limit frame request to send counter to 7
1234 if (uiFrameCount
> 0) {
1235 EplDllkInstance_g
.m_bFlag2
=
1236 (BYTE
) (((AsyncReqPriority
<<
1237 EPL_FRAME_FLAG2_PR_SHIFT
)
1238 & EPL_FRAME_FLAG2_PR
)
1240 EPL_FRAME_FLAG2_RS
));
1242 EplDllkInstance_g
.m_bFlag2
= 0;
1249 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1250 case kEplEventTypeDllkStartReducedCycle
:
1252 // start the reduced cycle by programming the cycle timer
1253 // it is issued by NMT MN module, when PreOp1 is entered
1255 // clear the asynchronous queues
1256 Ret
= EplDllkCalAsyncClearQueues();
1258 // reset cycle counter (everytime a SoA is triggerd in PreOp1 the counter is incremented
1259 // and when it reaches EPL_C_DLL_PREOP1_START_CYCLES the SoA may contain invitations)
1260 EplDllkInstance_g
.m_uiCycleCount
= 0;
1262 // remove any CN from isochronous phase
1263 while (EplDllkInstance_g
.m_pFirstNodeInfo
!= NULL
) {
1264 EplDllkDeleteNode(EplDllkInstance_g
.
1265 m_pFirstNodeInfo
->m_uiNodeId
);
1268 // change state to NonCyclic,
1269 // hence EplDllkChangeState() will not ignore the next call
1270 EplDllkInstance_g
.m_DllState
= kEplDllMsNonCyclic
;
1272 #if EPL_TIMER_USE_HIGHRES != FALSE
1273 if (EplDllkInstance_g
.m_DllConfigParam
.
1274 m_dwAsyncSlotTimeout
!= 0) {
1276 EplTimerHighReskModifyTimerNs
1277 (&EplDllkInstance_g
.m_TimerHdlCycle
,
1278 EplDllkInstance_g
.m_DllConfigParam
.
1279 m_dwAsyncSlotTimeout
,
1280 EplDllkCbMnTimerCycle
, 0L, FALSE
);
1288 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
1289 case kEplEventTypeDllkPresReady
:
1291 // post PRes to transmit FIFO
1293 NmtState
= EplNmtkGetNmtState();
1295 if (NmtState
!= kEplNmtCsBasicEthernet
) {
1297 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
].m_pbBuffer
!= NULL
) { // PRes does exist
1299 (tEplFrame
*) EplDllkInstance_g
.
1300 m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
].
1302 // update frame (NMT state, RD, RS, PR, MS, EN flags)
1303 if (NmtState
< kEplNmtCsPreOperational2
) { // NMT state is not PreOp2, ReadyToOp or Op
1304 // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
1306 kEplNmtCsPreOperational2
;
1308 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
1311 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
1315 if (NmtState
!= kEplNmtCsOperational
) { // mark PDO as invalid in NMT state Op
1316 // $$$ reset only RD flag; set other flags appropriately
1317 AmiSetByteToLe(&pTxFrame
->
1321 // $$$ make function that updates Pres, StatusRes
1322 // mark PRes frame as ready for transmission
1324 EdrvTxMsgReady(&EplDllkInstance_g
.
1326 [EPL_DLLK_TXFRAME_PRES
]);
1336 "EplDllkProcess(): unhandled event type!\n");
1344 //---------------------------------------------------------------------------
1346 // Function: EplDllkConfig
1348 // Description: configure parameters of DLL
1350 // Parameters: pDllConfigParam_p = configuration parameters
1352 // Returns: tEplKernel = error code
1357 //---------------------------------------------------------------------------
1359 tEplKernel
EplDllkConfig(tEplDllConfigParam
* pDllConfigParam_p
)
1361 tEplKernel Ret
= kEplSuccessful
;
1363 // d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
1364 /*tEplNmtState NmtState;
1366 NmtState = EplNmtkGetNmtState();
1368 if (NmtState > kEplNmtGsResetConfiguration)
1369 { // only allowed in state DLL_GS_INIT
1370 Ret = kEplInvalidOperation;
1374 EPL_MEMCPY(&EplDllkInstance_g
.m_DllConfigParam
, pDllConfigParam_p
,
1375 (pDllConfigParam_p
->m_uiSizeOfStruct
<
1376 sizeof(tEplDllConfigParam
) ? pDllConfigParam_p
->
1377 m_uiSizeOfStruct
: sizeof(tEplDllConfigParam
)));
1379 if ((EplDllkInstance_g
.m_DllConfigParam
.m_dwCycleLen
!= 0)
1380 && (EplDllkInstance_g
.m_DllConfigParam
.m_dwLossOfFrameTolerance
!= 0)) { // monitor EPL cycle, calculate frame timeout
1381 EplDllkInstance_g
.m_ullFrameTimeout
= (1000LL
1383 ((unsigned long long)
1388 ((unsigned long long)EplDllkInstance_g
.m_DllConfigParam
.
1389 m_dwLossOfFrameTolerance
);
1391 EplDllkInstance_g
.m_ullFrameTimeout
= 0LL;
1394 if (EplDllkInstance_g
.m_DllConfigParam
.m_fAsyncOnly
!= FALSE
) { // it is configured as async-only CN
1395 // disable multiplexed cycle, that m_uiCycleCount will not be incremented spuriously on SoC
1396 EplDllkInstance_g
.m_DllConfigParam
.m_uiMultiplCycleCnt
= 0;
1402 //---------------------------------------------------------------------------
1404 // Function: EplDllkSetIdentity
1406 // Description: configure identity of local node for IdentResponse
1408 // Parameters: pDllIdentParam_p = identity
1410 // Returns: tEplKernel = error code
1415 //---------------------------------------------------------------------------
1417 tEplKernel
EplDllkSetIdentity(tEplDllIdentParam
* pDllIdentParam_p
)
1419 tEplKernel Ret
= kEplSuccessful
;
1421 EPL_MEMCPY(&EplDllkInstance_g
.m_DllIdentParam
, pDllIdentParam_p
,
1422 (pDllIdentParam_p
->m_uiSizeOfStruct
<
1423 sizeof(tEplDllIdentParam
) ? pDllIdentParam_p
->
1424 m_uiSizeOfStruct
: sizeof(tEplDllIdentParam
)));
1426 // $$$ if IdentResponse frame exists update it
1431 //---------------------------------------------------------------------------
1433 // Function: EplDllkRegAsyncHandler
1435 // Description: registers handler for non-EPL frames
1437 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1439 // Returns: tEplKernel = error code
1444 //---------------------------------------------------------------------------
1446 tEplKernel
EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p
)
1448 tEplKernel Ret
= kEplSuccessful
;
1450 if (EplDllkInstance_g
.m_pfnCbAsync
== NULL
) { // no handler registered yet
1451 EplDllkInstance_g
.m_pfnCbAsync
= pfnDllkCbAsync_p
;
1452 } else { // handler already registered
1453 Ret
= kEplDllCbAsyncRegistered
;
1459 //---------------------------------------------------------------------------
1461 // Function: EplDllkDeregAsyncHandler
1463 // Description: deregisters handler for non-EPL frames
1465 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1467 // Returns: tEplKernel = error code
1472 //---------------------------------------------------------------------------
1474 tEplKernel
EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p
)
1476 tEplKernel Ret
= kEplSuccessful
;
1478 if (EplDllkInstance_g
.m_pfnCbAsync
== pfnDllkCbAsync_p
) { // same handler is registered
1480 EplDllkInstance_g
.m_pfnCbAsync
= NULL
;
1481 } else { // wrong handler or no handler registered
1482 Ret
= kEplDllCbAsyncRegistered
;
1488 //---------------------------------------------------------------------------
1490 // Function: EplDllkSetAsndServiceIdFilter()
1492 // Description: sets the specified node ID filter for the specified
1493 // AsndServiceId. It registers C_DLL_MULTICAST_ASND in ethernet
1494 // driver if any AsndServiceId is open.
1496 // Parameters: ServiceId_p = ASnd Service ID
1497 // Filter_p = node ID filter
1499 // Returns: tEplKernel = error code
1504 //---------------------------------------------------------------------------
1506 tEplKernel
EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p
,
1507 tEplDllAsndFilter Filter_p
)
1509 tEplKernel Ret
= kEplSuccessful
;
1511 if (ServiceId_p
< tabentries(EplDllkInstance_g
.m_aAsndFilter
)) {
1512 EplDllkInstance_g
.m_aAsndFilter
[ServiceId_p
] = Filter_p
;
1518 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1520 //---------------------------------------------------------------------------
1522 // Function: EplDllkSetFlag1OfNode()
1524 // Description: sets Flag1 (for PReq and SoA) of the specified node ID.
1526 // Parameters: uiNodeId_p = node ID
1527 // bSoaFlag1_p = flag1
1529 // Returns: tEplKernel = error code
1534 //---------------------------------------------------------------------------
1536 tEplKernel
EplDllkSetFlag1OfNode(unsigned int uiNodeId_p
, BYTE bSoaFlag1_p
)
1538 tEplKernel Ret
= kEplSuccessful
;
1539 tEplDllkNodeInfo
*pNodeInfo
;
1541 pNodeInfo
= EplDllkGetNodeInfo(uiNodeId_p
);
1542 if (pNodeInfo
== NULL
) { // no node info structure available
1543 Ret
= kEplDllNoNodeInfo
;
1546 // store flag1 in internal node info structure
1547 pNodeInfo
->m_bSoaFlag1
= bSoaFlag1_p
;
1553 //---------------------------------------------------------------------------
1555 // Function: EplDllkGetFirstNodeInfo()
1557 // Description: returns first info structure of first node in isochronous phase.
1558 // It is only useful for ErrorHandlerk module.
1560 // Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure
1562 // Returns: tEplKernel = error code
1567 //---------------------------------------------------------------------------
1569 tEplKernel
EplDllkGetFirstNodeInfo(tEplDllkNodeInfo
** ppNodeInfo_p
)
1571 tEplKernel Ret
= kEplSuccessful
;
1573 *ppNodeInfo_p
= EplDllkInstance_g
.m_pFirstNodeInfo
;
1578 //---------------------------------------------------------------------------
1580 // Function: EplDllkAddNode()
1582 // Description: adds the specified node to the isochronous phase.
1584 // Parameters: pNodeInfo_p = pointer of node info structure
1586 // Returns: tEplKernel = error code
1591 //---------------------------------------------------------------------------
1593 tEplKernel
EplDllkAddNode(tEplDllNodeInfo
* pNodeInfo_p
)
1595 tEplKernel Ret
= kEplSuccessful
;
1596 tEplDllkNodeInfo
*pIntNodeInfo
;
1597 tEplDllkNodeInfo
**ppIntNodeInfo
;
1598 unsigned int uiHandle
;
1600 unsigned int uiFrameSize
;
1602 pIntNodeInfo
= EplDllkGetNodeInfo(pNodeInfo_p
->m_uiNodeId
);
1603 if (pIntNodeInfo
== NULL
) { // no node info structure available
1604 Ret
= kEplDllNoNodeInfo
;
1608 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode
,
1609 pNodeInfo_p
->m_uiNodeId
, 0);
1611 // copy node configuration
1612 pIntNodeInfo
->m_dwPresTimeout
= pNodeInfo_p
->m_dwPresTimeout
;
1613 pIntNodeInfo
->m_wPresPayloadLimit
= pNodeInfo_p
->m_wPresPayloadLimit
;
1615 // $$$ d.k.: actually add node only if MN. On CN it is sufficient to update the node configuration
1616 if (pNodeInfo_p
->m_uiNodeId
== EplDllkInstance_g
.m_DllConfigParam
.m_uiNodeId
) { // we shall send PRes ourself
1617 // insert our node at the end of the list
1618 ppIntNodeInfo
= &EplDllkInstance_g
.m_pFirstNodeInfo
;
1619 while ((*ppIntNodeInfo
!= NULL
)
1620 && ((*ppIntNodeInfo
)->m_pNextNodeInfo
!= NULL
)) {
1621 ppIntNodeInfo
= &(*ppIntNodeInfo
)->m_pNextNodeInfo
;
1623 if (*ppIntNodeInfo
!= NULL
) {
1624 if ((*ppIntNodeInfo
)->m_uiNodeId
== pNodeInfo_p
->m_uiNodeId
) { // node was already added to list
1625 // $$$ d.k. maybe this should be an error
1627 } else { // add our node at the end of the list
1629 &(*ppIntNodeInfo
)->m_pNextNodeInfo
;
1632 // set "PReq"-TxBuffer to PRes-TxBuffer
1633 pIntNodeInfo
->m_pPreqTxBuffer
=
1634 &EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
];
1635 } else { // normal CN shall be added to isochronous phase
1636 // insert node into list in ascending order
1637 ppIntNodeInfo
= &EplDllkInstance_g
.m_pFirstNodeInfo
;
1638 while ((*ppIntNodeInfo
!= NULL
)
1639 && ((*ppIntNodeInfo
)->m_uiNodeId
<
1640 pNodeInfo_p
->m_uiNodeId
)
1641 && ((*ppIntNodeInfo
)->m_uiNodeId
!=
1642 EplDllkInstance_g
.m_DllConfigParam
.m_uiNodeId
)) {
1643 ppIntNodeInfo
= &(*ppIntNodeInfo
)->m_pNextNodeInfo
;
1645 if ((*ppIntNodeInfo
!= NULL
) && ((*ppIntNodeInfo
)->m_uiNodeId
== pNodeInfo_p
->m_uiNodeId
)) { // node was already added to list
1646 // $$$ d.k. maybe this should be an error
1651 // initialize elements of internal node info structure
1652 pIntNodeInfo
->m_bSoaFlag1
= 0;
1653 pIntNodeInfo
->m_fSoftDelete
= FALSE
;
1654 pIntNodeInfo
->m_NmtState
= kEplNmtCsNotActive
;
1655 if (pIntNodeInfo
->m_pPreqTxBuffer
== NULL
) { // create TxBuffer entry
1656 uiFrameSize
= pNodeInfo_p
->m_wPreqPayloadLimit
+ 24;
1658 EplDllkCreateTxFrame(&uiHandle
, &pFrame
, &uiFrameSize
,
1660 kEplDllAsndNotDefined
);
1661 if (Ret
!= kEplSuccessful
) {
1664 pIntNodeInfo
->m_pPreqTxBuffer
=
1665 &EplDllkInstance_g
.m_pTxBuffer
[uiHandle
];
1666 AmiSetByteToLe(&pFrame
->m_le_bDstNodeId
,
1667 (BYTE
) pNodeInfo_p
->m_uiNodeId
);
1669 // set up destination MAC address
1670 EPL_MEMCPY(pFrame
->m_be_abDstMac
, pIntNodeInfo
->m_be_abMacAddr
,
1673 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
1675 tEplFrameInfo FrameInfo
;
1677 // initially encode TPDO -> inform PDO module
1678 FrameInfo
.m_pFrame
= pFrame
;
1679 FrameInfo
.m_uiFrameSize
= uiFrameSize
;
1680 Ret
= EplPdokCbPdoTransmitted(&FrameInfo
);
1684 pIntNodeInfo
->m_ulDllErrorEvents
= 0L;
1686 pIntNodeInfo
->m_pNextNodeInfo
= *ppIntNodeInfo
;
1687 *ppIntNodeInfo
= pIntNodeInfo
;
1693 //---------------------------------------------------------------------------
1695 // Function: EplDllkDeleteNode()
1697 // Description: removes the specified node from the isochronous phase.
1699 // Parameters: uiNodeId_p = node ID
1701 // Returns: tEplKernel = error code
1706 //---------------------------------------------------------------------------
1708 tEplKernel
EplDllkDeleteNode(unsigned int uiNodeId_p
)
1710 tEplKernel Ret
= kEplSuccessful
;
1711 tEplDllkNodeInfo
*pIntNodeInfo
;
1712 tEplDllkNodeInfo
**ppIntNodeInfo
;
1713 unsigned int uiHandle
;
1715 pIntNodeInfo
= EplDllkGetNodeInfo(uiNodeId_p
);
1716 if (pIntNodeInfo
== NULL
) { // no node info structure available
1717 Ret
= kEplDllNoNodeInfo
;
1721 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode
, uiNodeId_p
, 0);
1723 // search node in whole list
1724 ppIntNodeInfo
= &EplDllkInstance_g
.m_pFirstNodeInfo
;
1725 while ((*ppIntNodeInfo
!= NULL
)
1726 && ((*ppIntNodeInfo
)->m_uiNodeId
!= uiNodeId_p
)) {
1727 ppIntNodeInfo
= &(*ppIntNodeInfo
)->m_pNextNodeInfo
;
1729 if ((*ppIntNodeInfo
== NULL
) || ((*ppIntNodeInfo
)->m_uiNodeId
!= uiNodeId_p
)) { // node was not found in list
1730 // $$$ d.k. maybe this should be an error
1733 // remove node from list
1734 *ppIntNodeInfo
= pIntNodeInfo
->m_pNextNodeInfo
;
1736 if ((pIntNodeInfo
->m_pPreqTxBuffer
!= NULL
)
1737 && (pIntNodeInfo
->m_pPreqTxBuffer
!= &EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
])) { // delete TxBuffer entry
1739 pIntNodeInfo
->m_pPreqTxBuffer
-
1740 EplDllkInstance_g
.m_pTxBuffer
;
1741 pIntNodeInfo
->m_pPreqTxBuffer
= NULL
;
1742 Ret
= EplDllkDeleteTxFrame(uiHandle
);
1743 /* if (Ret != kEplSuccessful)
1753 //---------------------------------------------------------------------------
1755 // Function: EplDllkSoftDeleteNode()
1757 // Description: removes the specified node not immediately from the isochronous phase.
1758 // Instead the will be removed after error (late/loss PRes) without
1759 // charging the error.
1761 // Parameters: uiNodeId_p = node ID
1763 // Returns: tEplKernel = error code
1768 //---------------------------------------------------------------------------
1770 tEplKernel
EplDllkSoftDeleteNode(unsigned int uiNodeId_p
)
1772 tEplKernel Ret
= kEplSuccessful
;
1773 tEplDllkNodeInfo
*pIntNodeInfo
;
1775 pIntNodeInfo
= EplDllkGetNodeInfo(uiNodeId_p
);
1776 if (pIntNodeInfo
== NULL
) { // no node info structure available
1777 Ret
= kEplDllNoNodeInfo
;
1781 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode
,
1784 pIntNodeInfo
->m_fSoftDelete
= TRUE
;
1790 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1792 //=========================================================================//
1794 // P R I V A T E F U N C T I O N S //
1796 //=========================================================================//
1798 //---------------------------------------------------------------------------
1800 // Function: EplDllkChangeState
1802 // Description: change DLL state on event and diagnose some communication errors
1804 // Parameters: NmtEvent_p = DLL event (wrapped in NMT event)
1806 // Returns: tEplKernel = error code
1811 //---------------------------------------------------------------------------
1813 static tEplKernel
EplDllkChangeState(tEplNmtEvent NmtEvent_p
,
1814 tEplNmtState NmtState_p
)
1816 tEplKernel Ret
= kEplSuccessful
;
1818 tEplErrorHandlerkEvent DllEvent
;
1820 DllEvent
.m_ulDllErrorEvents
= 0;
1821 DllEvent
.m_uiNodeId
= 0;
1822 DllEvent
.m_NmtState
= NmtState_p
;
1824 switch (NmtState_p
) {
1826 case kEplNmtGsInitialising
:
1827 case kEplNmtGsResetApplication
:
1828 case kEplNmtGsResetCommunication
:
1829 case kEplNmtGsResetConfiguration
:
1830 case kEplNmtCsBasicEthernet
:
1831 // enter DLL_GS_INIT
1832 EplDllkInstance_g
.m_DllState
= kEplDllGsInit
;
1835 case kEplNmtCsNotActive
:
1836 case kEplNmtCsPreOperational1
:
1837 // reduced EPL cycle is active
1838 if (NmtEvent_p
== kEplNmtEventDllCeSoc
) { // SoC received
1839 // enter DLL_CS_WAIT_PREQ
1840 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitPreq
;
1842 // enter DLL_GS_INIT
1843 EplDllkInstance_g
.m_DllState
= kEplDllGsInit
;
1847 case kEplNmtCsPreOperational2
:
1848 case kEplNmtCsReadyToOperate
:
1849 case kEplNmtCsOperational
:
1850 // full EPL cycle is active
1852 switch (EplDllkInstance_g
.m_DllState
) {
1853 case kEplDllCsWaitPreq
:
1854 switch (NmtEvent_p
) {
1856 case kEplNmtEventDllCePreq
:
1857 // enter DLL_CS_WAIT_SOA
1858 DllEvent
.m_ulDllErrorEvents
|=
1859 EPL_DLL_ERR_CN_RECVD_PREQ
;
1860 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoa
;
1864 case kEplNmtEventDllCeFrameTimeout
:
1865 if (NmtState_p
== kEplNmtCsPreOperational2
) { // ignore frame timeout in PreOp2,
1866 // because the previously configured cycle len
1868 // 2008/10/15 d.k. If it would not be ignored,
1869 // we would go cyclically to PreOp1 and on next
1870 // SoC back to PreOp2.
1873 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
1874 DllEvent
.m_ulDllErrorEvents
|=
1875 EPL_DLL_ERR_CN_LOSS_SOA
|
1876 EPL_DLL_ERR_CN_LOSS_SOC
;
1878 // enter DLL_CS_WAIT_SOC
1879 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoc
;
1882 case kEplNmtEventDllCeSoa
:
1883 // check if multiplexed and PReq should have been received in this cycle
1884 // and if >= NMT_CS_READY_TO_OPERATE
1885 if ((EplDllkInstance_g
.m_uiCycleCount
== 0)
1886 && (NmtState_p
>= kEplNmtCsReadyToOperate
)) { // report DLL_CEV_LOSS_OF_PREQ
1887 DllEvent
.m_ulDllErrorEvents
|=
1888 EPL_DLL_ERR_CN_LOSS_PREQ
;
1890 // enter DLL_CS_WAIT_SOC
1891 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoc
;
1895 case kEplNmtEventDllCeSoc
:
1896 case kEplNmtEventDllCeAsnd
:
1897 // report DLL_CEV_LOSS_SOA
1898 DllEvent
.m_ulDllErrorEvents
|=
1899 EPL_DLL_ERR_CN_LOSS_SOA
;
1901 case kEplNmtEventDllCePres
:
1903 // remain in this state
1908 case kEplDllCsWaitSoc
:
1909 switch (NmtEvent_p
) {
1911 case kEplNmtEventDllCeSoc
:
1912 // start of cycle and isochronous phase
1913 // enter DLL_CS_WAIT_PREQ
1914 EplDllkInstance_g
.m_DllState
=
1919 // case kEplNmtEventDllCePres:
1920 case kEplNmtEventDllCeFrameTimeout
:
1921 if (NmtState_p
== kEplNmtCsPreOperational2
) { // ignore frame timeout in PreOp2,
1922 // because the previously configured cycle len
1924 // 2008/10/15 d.k. If it would not be ignored,
1925 // we would go cyclically to PreOp1 and on next
1926 // SoC back to PreOp2.
1931 case kEplNmtEventDllCePreq
:
1932 case kEplNmtEventDllCeSoa
:
1933 // report DLL_CEV_LOSS_SOC
1934 DllEvent
.m_ulDllErrorEvents
|=
1935 EPL_DLL_ERR_CN_LOSS_SOC
;
1937 case kEplNmtEventDllCeAsnd
:
1939 // remain in this state
1944 case kEplDllCsWaitSoa
:
1945 switch (NmtEvent_p
) {
1946 case kEplNmtEventDllCeFrameTimeout
:
1948 if (NmtState_p
== kEplNmtCsPreOperational2
) { // ignore frame timeout in PreOp2,
1949 // because the previously configured cycle len
1951 // 2008/10/15 d.k. If it would not be ignored,
1952 // we would go cyclically to PreOp1 and on next
1953 // SoC back to PreOp2.
1958 case kEplNmtEventDllCePreq
:
1959 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
1960 DllEvent
.m_ulDllErrorEvents
|=
1961 EPL_DLL_ERR_CN_LOSS_SOA
|
1962 EPL_DLL_ERR_CN_LOSS_SOC
;
1964 case kEplNmtEventDllCeSoa
:
1965 // enter DLL_CS_WAIT_SOC
1966 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoc
;
1970 case kEplNmtEventDllCeSoc
:
1971 // report DLL_CEV_LOSS_SOA
1972 DllEvent
.m_ulDllErrorEvents
|=
1973 EPL_DLL_ERR_CN_LOSS_SOA
;
1975 // enter DLL_CS_WAIT_PREQ
1976 EplDllkInstance_g
.m_DllState
=
1981 case kEplNmtEventDllCeAsnd
:
1982 // report DLL_CEV_LOSS_SOA
1983 DllEvent
.m_ulDllErrorEvents
|=
1984 EPL_DLL_ERR_CN_LOSS_SOA
;
1986 case kEplNmtEventDllCePres
:
1988 // remain in this state
1994 // enter DLL_CS_WAIT_PREQ
1995 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitPreq
;
2003 case kEplNmtCsStopped
:
2004 // full EPL cycle is active, but without PReq/PRes
2006 switch (EplDllkInstance_g
.m_DllState
) {
2007 case kEplDllCsWaitPreq
:
2008 switch (NmtEvent_p
) {
2010 case kEplNmtEventDllCePreq
:
2011 // enter DLL_CS_WAIT_SOA
2012 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoa
;
2016 case kEplNmtEventDllCeFrameTimeout
:
2017 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
2018 DllEvent
.m_ulDllErrorEvents
|=
2019 EPL_DLL_ERR_CN_LOSS_SOA
|
2020 EPL_DLL_ERR_CN_LOSS_SOC
;
2022 case kEplNmtEventDllCeSoa
:
2023 // NMT_CS_STOPPED active
2024 // it is Ok if no PReq was received
2026 // enter DLL_CS_WAIT_SOC
2027 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoc
;
2031 case kEplNmtEventDllCeSoc
:
2032 case kEplNmtEventDllCeAsnd
:
2033 // report DLL_CEV_LOSS_SOA
2034 DllEvent
.m_ulDllErrorEvents
|=
2035 EPL_DLL_ERR_CN_LOSS_SOA
;
2037 case kEplNmtEventDllCePres
:
2039 // remain in this state
2044 case kEplDllCsWaitSoc
:
2045 switch (NmtEvent_p
) {
2047 case kEplNmtEventDllCeSoc
:
2048 // start of cycle and isochronous phase
2049 // enter DLL_CS_WAIT_SOA
2050 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoa
;
2054 // case kEplNmtEventDllCePres:
2055 case kEplNmtEventDllCePreq
:
2056 case kEplNmtEventDllCeSoa
:
2057 case kEplNmtEventDllCeFrameTimeout
:
2058 // report DLL_CEV_LOSS_SOC
2059 DllEvent
.m_ulDllErrorEvents
|=
2060 EPL_DLL_ERR_CN_LOSS_SOC
;
2062 case kEplNmtEventDllCeAsnd
:
2064 // remain in this state
2069 case kEplDllCsWaitSoa
:
2070 switch (NmtEvent_p
) {
2072 case kEplNmtEventDllCeFrameTimeout
:
2073 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
2074 DllEvent
.m_ulDllErrorEvents
|=
2075 EPL_DLL_ERR_CN_LOSS_SOA
|
2076 EPL_DLL_ERR_CN_LOSS_SOC
;
2078 case kEplNmtEventDllCeSoa
:
2079 // enter DLL_CS_WAIT_SOC
2080 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoc
;
2084 case kEplNmtEventDllCeSoc
:
2085 // report DLL_CEV_LOSS_SOA
2086 DllEvent
.m_ulDllErrorEvents
|=
2087 EPL_DLL_ERR_CN_LOSS_SOA
;
2088 // remain in DLL_CS_WAIT_SOA
2092 case kEplNmtEventDllCeAsnd
:
2093 // report DLL_CEV_LOSS_SOA
2094 DllEvent
.m_ulDllErrorEvents
|=
2095 EPL_DLL_ERR_CN_LOSS_SOA
;
2097 case kEplNmtEventDllCePreq
:
2098 // NMT_CS_STOPPED active and we do not expect any PReq
2099 // so just ignore it
2100 case kEplNmtEventDllCePres
:
2102 // remain in this state
2109 // enter DLL_CS_WAIT_PREQ
2110 EplDllkInstance_g
.m_DllState
= kEplDllCsWaitSoa
;
2115 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2116 case kEplNmtMsNotActive
:
2117 case kEplNmtMsBasicEthernet
:
2120 case kEplNmtMsPreOperational1
:
2121 // reduced EPL cycle is active
2122 if (EplDllkInstance_g
.m_DllState
!= kEplDllMsNonCyclic
) { // stop cycle timer
2123 #if EPL_TIMER_USE_HIGHRES != FALSE
2125 EplTimerHighReskDeleteTimer(&EplDllkInstance_g
.
2128 EplDllkInstance_g
.m_DllState
= kEplDllMsNonCyclic
;
2130 // stop further processing,
2131 // because it will be restarted by NMT MN module
2135 switch (NmtEvent_p
) {
2136 case kEplNmtEventDllMeSocTrig
:
2137 case kEplNmtEventDllCeAsnd
:
2138 { // because of reduced EPL cycle SoA shall be triggered, not SoC
2139 tEplDllState DummyDllState
;
2142 EplDllkAsyncFrameNotReceived
2143 (EplDllkInstance_g
.m_LastReqServiceId
,
2144 EplDllkInstance_g
.m_uiLastTargetNodeId
);
2146 // go ahead and send SoA
2147 Ret
= EplDllkMnSendSoa(NmtState_p
,
2151 EPL_C_DLL_PREOP1_START_CYCLES
));
2152 // increment cycle counter to detect if EPL_C_DLL_PREOP1_START_CYCLES empty cycles are elapsed
2153 EplDllkInstance_g
.m_uiCycleCount
++;
2156 #if EPL_TIMER_USE_HIGHRES != FALSE
2157 if (EplDllkInstance_g
.m_DllConfigParam
.
2158 m_dwAsyncSlotTimeout
!= 0) {
2160 EplTimerHighReskModifyTimerNs
2161 (&EplDllkInstance_g
.m_TimerHdlCycle
,
2162 EplDllkInstance_g
.m_DllConfigParam
.
2163 m_dwAsyncSlotTimeout
,
2164 EplDllkCbMnTimerCycle
, 0L, FALSE
);
2175 case kEplNmtMsPreOperational2
:
2176 case kEplNmtMsReadyToOperate
:
2177 case kEplNmtMsOperational
:
2178 // full EPL cycle is active
2179 switch (NmtEvent_p
) {
2180 case kEplNmtEventDllMeSocTrig
:
2182 // update cycle counter
2183 if (EplDllkInstance_g
.m_DllConfigParam
.m_uiMultiplCycleCnt
> 0) { // multiplexed cycle active
2184 EplDllkInstance_g
.m_uiCycleCount
=
2185 (EplDllkInstance_g
.m_uiCycleCount
+
2187 EplDllkInstance_g
.m_DllConfigParam
.
2188 m_uiMultiplCycleCnt
;
2189 // $$$ check multiplexed cycle restart
2190 // -> toggle MC flag
2191 // -> change node linked list
2192 } else { // non-multiplexed cycle active
2193 // start with first node in isochronous phase
2194 EplDllkInstance_g
.m_pCurNodeInfo
= NULL
;
2197 switch (EplDllkInstance_g
.m_DllState
) {
2198 case kEplDllMsNonCyclic
:
2199 { // start continuous cycle timer
2200 #if EPL_TIMER_USE_HIGHRES != FALSE
2202 EplTimerHighReskModifyTimerNs
2203 (&EplDllkInstance_g
.
2207 EplDllkCbMnTimerCycle
, 0L,
2210 // continue with sending SoC
2213 case kEplDllMsWaitAsnd
:
2214 case kEplDllMsWaitSocTrig
:
2215 { // if m_LastReqServiceId is still valid,
2216 // SoA was not correctly answered
2217 // and user part has to be informed
2219 EplDllkAsyncFrameNotReceived
2223 m_uiLastTargetNodeId
);
2226 Ret
= EplDllkMnSendSoc();
2229 EplDllkInstance_g
.m_DllState
=
2230 kEplDllMsWaitPreqTrig
;
2232 // start WaitSoCPReq Timer
2233 #if EPL_TIMER_USE_HIGHRES != FALSE
2235 EplTimerHighReskModifyTimerNs
2236 (&EplDllkInstance_g
.
2241 EplDllkCbMnTimerResponse
,
2248 { // wrong DLL state / cycle time exceeded
2249 DllEvent
.m_ulDllErrorEvents
|=
2250 EPL_DLL_ERR_MN_CYCTIMEEXCEED
;
2251 EplDllkInstance_g
.m_DllState
=
2252 kEplDllMsWaitSocTrig
;
2260 case kEplNmtEventDllMePresTimeout
:
2263 switch (EplDllkInstance_g
.m_DllState
) {
2264 case kEplDllMsWaitPres
:
2265 { // PRes not received
2267 if (EplDllkInstance_g
.m_pCurNodeInfo
->m_fSoftDelete
== FALSE
) { // normal isochronous CN
2271 EPL_DLL_ERR_MN_CN_LOSS_PRES
;
2272 DllEvent
.m_uiNodeId
=
2276 } else { // CN shall be deleted softly
2278 kEplEventSinkDllkCal
;
2280 kEplEventTypeDllkSoftDelNode
;
2281 // $$$ d.k. set Event.m_NetTime to current time
2294 // continue with sending next PReq
2297 case kEplDllMsWaitPreqTrig
:
2310 { // wrong DLL state
2318 case kEplNmtEventDllCePres
:
2321 switch (EplDllkInstance_g
.m_DllState
) {
2322 case kEplDllMsWaitPres
:
2335 { // wrong DLL state
2343 case kEplNmtEventDllMeSoaTrig
:
2346 switch (EplDllkInstance_g
.m_DllState
) {
2347 case kEplDllMsWaitSoaTrig
:
2351 EplDllkMnSendSoa(NmtState_p
,
2360 { // wrong DLL state
2368 case kEplNmtEventDllCeAsnd
:
2369 { // ASnd has been received, but it may be not the requested one
2371 // report if SoA was correctly answered
2372 Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId,
2373 EplDllkInstance_g.m_uiLastTargetNodeId);
2375 if (EplDllkInstance_g
.m_DllState
==
2376 kEplDllMsWaitAsnd
) {
2377 EplDllkInstance_g
.m_DllState
=
2378 kEplDllMsWaitSocTrig
;
2387 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2393 if (DllEvent
.m_ulDllErrorEvents
!= 0) { // error event set -> post it to error handler
2394 Event
.m_EventSink
= kEplEventSinkErrk
;
2395 Event
.m_EventType
= kEplEventTypeDllError
;
2396 // $$$ d.k. set Event.m_NetTime to current time
2397 Event
.m_uiSize
= sizeof(DllEvent
);
2398 Event
.m_pArg
= &DllEvent
;
2399 Ret
= EplEventkPost(&Event
);
2405 //---------------------------------------------------------------------------
2407 // Function: EplDllkCbFrameReceived()
2409 // Description: called from EdrvInterruptHandler()
2411 // Parameters: pRxBuffer_p = receive buffer structure
2418 //---------------------------------------------------------------------------
2420 static void EplDllkCbFrameReceived(tEdrvRxBuffer
* pRxBuffer_p
)
2422 tEplKernel Ret
= kEplSuccessful
;
2423 tEplNmtState NmtState
;
2424 tEplNmtEvent NmtEvent
= kEplNmtEventNoEvent
;
2427 tEplFrame
*pTxFrame
;
2428 tEdrvTxBuffer
*pTxBuffer
= NULL
;
2429 tEplFrameInfo FrameInfo
;
2430 tEplMsgType MsgType
;
2431 tEplDllReqServiceId ReqServiceId
;
2432 unsigned int uiAsndServiceId
;
2433 unsigned int uiNodeId
;
2436 BENCHMARK_MOD_02_SET(3);
2437 NmtState
= EplNmtkGetNmtState();
2439 if (NmtState
<= kEplNmtGsResetConfiguration
) {
2443 pFrame
= (tEplFrame
*) pRxBuffer_p
->m_pbBuffer
;
2445 #if EDRV_EARLY_RX_INT != FALSE
2446 switch (pRxBuffer_p
->m_BufferInFrame
) {
2447 case kEdrvBufferFirstInFrame
:
2450 (tEplMsgType
) AmiGetByteFromLe(&pFrame
->
2452 if (MsgType
== kEplMsgTypePreq
) {
2453 if (EplDllkInstance_g
.m_DllState
== kEplDllCsWaitPreq
) { // PReq expected and actually received
2454 // d.k.: The condition above is sufficent, because EPL cycle is active
2455 // and no non-EPL frame shall be received in isochronous phase.
2456 // start transmission PRes
2457 // $$$ What if Tx buffer is invalid?
2460 m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
];
2461 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2462 Ret
= EdrvTxMsgStart(pTxBuffer
);
2465 (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
2466 // update frame (NMT state, RD, RS, PR, MS, EN flags)
2467 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2470 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2474 if (NmtState
!= kEplNmtCsOperational
) { // mark PDO as invalid in NMT state Op
2475 // $$$ reset only RD flag; set other flags appropriately
2476 AmiSetByteToLe(&pTxFrame
->
2480 // $$$ make function that updates Pres, StatusRes
2482 Ret
= EdrvSendTxMsg(pTxBuffer
);
2489 case kEdrvBufferMiddleInFrame
:
2494 case kEdrvBufferLastInFrame
:
2501 FrameInfo
.m_pFrame
= pFrame
;
2502 FrameInfo
.m_uiFrameSize
= pRxBuffer_p
->m_uiRxMsgLen
;
2503 FrameInfo
.m_NetTime
.m_dwNanoSec
= pRxBuffer_p
->m_NetTime
.m_dwNanoSec
;
2504 FrameInfo
.m_NetTime
.m_dwSec
= pRxBuffer_p
->m_NetTime
.m_dwSec
;
2506 if (AmiGetWordFromBe(&pFrame
->m_be_wEtherType
) != EPL_C_DLL_ETHERTYPE_EPL
) { // non-EPL frame
2507 //TRACE2("EplDllkCbFrameReceived: pfnCbAsync=0x%p SrcMAC=0x%llx\n", EplDllkInstance_g.m_pfnCbAsync, AmiGetQword48FromBe(pFrame->m_be_abSrcMac));
2508 if (EplDllkInstance_g
.m_pfnCbAsync
!= NULL
) { // handler for async frames is registered
2509 EplDllkInstance_g
.m_pfnCbAsync(&FrameInfo
);
2515 MsgType
= (tEplMsgType
) AmiGetByteFromLe(&pFrame
->m_le_bMessageType
);
2517 case kEplMsgTypePreq
:
2520 // d.k.: (we assume that this PReq frame is intended for us and don't check DstNodeId)
2521 if (AmiGetByteFromLe(&pFrame
->m_le_bDstNodeId
) != EplDllkInstance_g
.m_DllConfigParam
.m_uiNodeId
) { // this PReq is not intended for us
2524 NmtEvent
= kEplNmtEventDllCePreq
;
2526 if (NmtState
>= kEplNmtMsNotActive
) { // MN is active -> wrong msg type
2529 #if EDRV_EARLY_RX_INT == FALSE
2530 if (NmtState
>= kEplNmtCsPreOperational2
) { // respond to and process PReq frames only in PreOp2, ReadyToOp and Op
2534 m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
];
2535 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // PRes does exist
2536 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2537 EdrvTxMsgStart(pTxBuffer
);
2540 (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
2541 // update frame (NMT state, RD, RS, PR, MS, EN flags)
2542 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2545 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2550 AmiGetByteFromLe(&pFrame
->m_Data
.
2554 EplDllkInstance_g
.m_bMnFlag1
=
2556 m_bMnFlag1
& ~EPL_FRAME_FLAG1_EA
)
2557 | (bFlag1
& EPL_FRAME_FLAG1_EA
);
2559 bFlag1
&= EPL_FRAME_FLAG1_MS
;
2560 // add EN flag from Error signaling module
2563 m_bFlag1
& EPL_FRAME_FLAG1_EN
;
2564 if (NmtState
!= kEplNmtCsOperational
) { // mark PDO as invalid in NMT state Op
2565 // reset only RD flag
2566 AmiSetByteToLe(&pTxFrame
->
2570 } else { // leave RD flag untouched
2571 AmiSetByteToLe(&pTxFrame
->
2581 // $$$ update EPL_DLL_PRES_READY_AFTER_* code
2583 Ret
= EdrvSendTxMsg(pTxBuffer
);
2584 if (Ret
!= kEplSuccessful
) {
2590 // inform PDO module
2591 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2592 if (NmtState
>= kEplNmtCsReadyToOperate
) { // inform PDO module only in ReadyToOp and Op
2593 if (NmtState
!= kEplNmtCsOperational
) {
2594 // reset RD flag and all other flags, but that does not matter, because they were processed above
2595 AmiSetByteToLe(&pFrame
->m_Data
.
2599 // compares real frame size and PDO size
2601 int)(AmiGetWordFromLe(&pFrame
->
2606 > FrameInfo
.m_uiFrameSize
) { // format error
2607 tEplErrorHandlerkEvent DllEvent
;
2609 DllEvent
.m_ulDllErrorEvents
=
2610 EPL_DLL_ERR_INVALID_FORMAT
;
2611 DllEvent
.m_uiNodeId
=
2612 AmiGetByteFromLe(&pFrame
->
2614 DllEvent
.m_NmtState
= NmtState
;
2618 kEplEventTypeDllError
;
2620 FrameInfo
.m_NetTime
;
2623 Event
.m_pArg
= &DllEvent
;
2624 Ret
= EplEventkPost(&Event
);
2627 // forward PReq frame as RPDO to PDO module
2628 Ret
= EplPdokCbPdoReceived(&FrameInfo
);
2631 #if (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2632 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // PRes does exist
2633 // inform PDO module about PRes after PReq
2634 FrameInfo
.m_pFrame
=
2635 (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
2636 FrameInfo
.m_uiFrameSize
=
2637 pTxBuffer
->m_uiMaxBufferLen
;
2639 EplPdokCbPdoTransmitted(&FrameInfo
);
2644 #if EDRV_EARLY_RX_INT == FALSE
2645 // $$$ inform emergency protocol handling (error signaling module) about flags
2649 // reset cycle counter
2650 EplDllkInstance_g
.m_uiCycleCount
= 0;
2655 case kEplMsgTypePres
:
2657 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2658 tEplDllkNodeInfo
*pIntNodeInfo
;
2659 tEplHeartbeatEvent HeartbeatEvent
;
2663 NmtEvent
= kEplNmtEventDllCePres
;
2665 uiNodeId
= AmiGetByteFromLe(&pFrame
->m_le_bSrcNodeId
);
2667 if ((NmtState
>= kEplNmtCsPreOperational2
)
2668 && (NmtState
<= kEplNmtCsOperational
)) { // process PRes frames only in PreOp2, ReadyToOp and Op of CN
2670 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2671 pIntNodeInfo
= EplDllkGetNodeInfo(uiNodeId
);
2672 if (pIntNodeInfo
== NULL
) { // no node info structure available
2673 Ret
= kEplDllNoNodeInfo
;
2676 } else if (EplDllkInstance_g
.m_DllState
== kEplDllMsWaitPres
) { // or process PRes frames in MsWaitPres
2678 pIntNodeInfo
= EplDllkInstance_g
.m_pCurNodeInfo
;
2679 if ((pIntNodeInfo
== NULL
) || (pIntNodeInfo
->m_uiNodeId
!= uiNodeId
)) { // ignore PRes, because it is from wrong CN
2680 // $$$ maybe post event to NmtMn module
2683 // forward Flag2 to asynchronous scheduler
2685 AmiGetByteFromLe(&pFrame
->m_Data
.m_Asnd
.
2686 m_Payload
.m_StatusResponse
.
2689 EplDllkCalAsyncSetPendingRequests(uiNodeId
,
2690 ((tEplDllAsyncReqPriority
) ((bFlag1
& EPL_FRAME_FLAG2_PR
) >> EPL_FRAME_FLAG2_PR_SHIFT
)), (bFlag1
& EPL_FRAME_FLAG2_RS
));
2693 } else { // ignore PRes, because it was received in wrong NMT state
2694 // but execute EplDllkChangeState() and post event to NMT module
2698 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2699 { // check NMT state of CN
2700 HeartbeatEvent
.m_wErrorCode
= EPL_E_NO_ERROR
;
2701 HeartbeatEvent
.m_NmtState
=
2702 (tEplNmtState
) (AmiGetByteFromLe
2703 (&pFrame
->m_Data
.m_Pres
.
2706 if (pIntNodeInfo
->m_NmtState
!= HeartbeatEvent
.m_NmtState
) { // NMT state of CN has changed -> post event to NmtMnu module
2707 if (pIntNodeInfo
->m_fSoftDelete
== FALSE
) { // normal isochronous CN
2708 HeartbeatEvent
.m_uiNodeId
=
2711 kEplEventSinkNmtMnu
;
2713 kEplEventTypeHeartbeat
;
2715 sizeof(HeartbeatEvent
);
2716 Event
.m_pArg
= &HeartbeatEvent
;
2717 } else { // CN shall be deleted softly
2719 kEplEventSinkDllkCal
;
2721 kEplEventTypeDllkSoftDelNode
;
2723 sizeof(unsigned int);
2725 &pIntNodeInfo
->m_uiNodeId
;
2727 Event
.m_NetTime
= FrameInfo
.m_NetTime
;
2728 Ret
= EplEventkPost(&Event
);
2730 // save current NMT state of CN in internal node structure
2731 pIntNodeInfo
->m_NmtState
=
2732 HeartbeatEvent
.m_NmtState
;
2737 // inform PDO module
2738 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2739 if ((NmtState
!= kEplNmtCsPreOperational2
)
2740 && (NmtState
!= kEplNmtMsPreOperational2
)) { // inform PDO module only in ReadyToOp and Op
2741 // compare real frame size and PDO size?
2743 int)(AmiGetWordFromLe(&pFrame
->m_Data
.
2744 m_Pres
.m_le_wSize
) +
2746 > FrameInfo
.m_uiFrameSize
)
2747 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2750 (&pFrame
->m_Data
.m_Pres
.m_le_wSize
) >
2751 pIntNodeInfo
->m_wPresPayloadLimit
)
2754 tEplErrorHandlerkEvent DllEvent
;
2756 DllEvent
.m_ulDllErrorEvents
=
2757 EPL_DLL_ERR_INVALID_FORMAT
;
2758 DllEvent
.m_uiNodeId
= uiNodeId
;
2759 DllEvent
.m_NmtState
= NmtState
;
2760 Event
.m_EventSink
= kEplEventSinkErrk
;
2762 kEplEventTypeDllError
;
2763 Event
.m_NetTime
= FrameInfo
.m_NetTime
;
2764 Event
.m_uiSize
= sizeof(DllEvent
);
2765 Event
.m_pArg
= &DllEvent
;
2766 Ret
= EplEventkPost(&Event
);
2769 if ((NmtState
!= kEplNmtCsOperational
)
2770 && (NmtState
!= kEplNmtMsOperational
)) {
2771 // reset RD flag and all other flags, but that does not matter, because they were processed above
2772 AmiSetByteToLe(&pFrame
->m_Data
.m_Pres
.
2775 Ret
= EplPdokCbPdoReceived(&FrameInfo
);
2782 case kEplMsgTypeSoc
:
2785 NmtEvent
= kEplNmtEventDllCeSoc
;
2787 if (NmtState
>= kEplNmtMsNotActive
) { // MN is active -> wrong msg type
2790 #if EPL_DLL_PRES_READY_AFTER_SOC != FALSE
2791 // post PRes to transmit FIFO of the ethernet controller, but don't start
2792 // transmission over bus
2795 m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
];
2797 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // PRes does exist
2798 pTxFrame
= (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
2799 // update frame (NMT state, RD, RS, PR, MS, EN flags)
2800 if (NmtState
< kEplNmtCsPreOperational2
) { // NMT state is not PreOp2, ReadyToOp or Op
2801 // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
2802 NmtState
= kEplNmtCsPreOperational2
;
2804 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2807 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2809 EplDllkInstance_g
.m_bFlag2
);
2810 if (NmtState
!= kEplNmtCsOperational
) { // mark PDO as invalid in NMT state Op
2811 // $$$ reset only RD flag; set other flags appropriately
2812 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.
2815 // $$$ make function that updates Pres, StatusRes
2816 // mark PRes frame as ready for transmission
2817 Ret
= EdrvTxMsgReady(pTxBuffer
);
2821 if (NmtState
>= kEplNmtCsPreOperational2
) { // SoC frames only in PreOp2, ReadyToOp and Op
2822 // trigger synchronous task
2823 Event
.m_EventSink
= kEplEventSinkSync
;
2824 Event
.m_EventType
= kEplEventTypeSync
;
2826 Ret
= EplEventkPost(&Event
);
2828 // update cycle counter
2829 if (EplDllkInstance_g
.m_DllConfigParam
.m_uiMultiplCycleCnt
> 0) { // multiplexed cycle active
2830 EplDllkInstance_g
.m_uiCycleCount
=
2831 (EplDllkInstance_g
.m_uiCycleCount
+
2833 EplDllkInstance_g
.m_DllConfigParam
.
2834 m_uiMultiplCycleCnt
;
2838 #if EPL_TIMER_USE_HIGHRES != FALSE
2839 if (EplDllkInstance_g
.m_ullFrameTimeout
!= 0) {
2841 EplTimerHighReskModifyTimerNs
2842 (&EplDllkInstance_g
.m_TimerHdlCycle
,
2843 EplDllkInstance_g
.m_ullFrameTimeout
,
2844 EplDllkCbCnTimer
, 0L, FALSE
);
2851 case kEplMsgTypeSoa
:
2854 NmtEvent
= kEplNmtEventDllCeSoa
;
2856 if (NmtState
>= kEplNmtMsNotActive
) { // MN is active -> wrong msg type
2862 if ((NmtState
& EPL_NMT_SUPERSTATE_MASK
) != EPL_NMT_CS_EPLMODE
) { // do not respond, if NMT state is < PreOp1 (i.e. not EPL_MODE)
2865 // check TargetNodeId
2867 AmiGetByteFromLe(&pFrame
->m_Data
.m_Soa
.
2868 m_le_bReqServiceTarget
);
2869 if (uiNodeId
== EplDllkInstance_g
.m_DllConfigParam
.m_uiNodeId
) { // local node is the target of the current request
2873 (tEplDllReqServiceId
)
2874 AmiGetByteFromLe(&pFrame
->m_Data
.m_Soa
.
2875 m_le_bReqServiceId
);
2876 if (ReqServiceId
== kEplDllReqServiceStatus
) { // StatusRequest
2877 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_STATUSRES
].m_pbBuffer
!= NULL
) { // StatusRes does exist
2883 [EPL_DLLK_TXFRAME_STATUSRES
].
2885 // update StatusRes frame (NMT state, EN, EC, RS, PR flags)
2886 AmiSetByteToLe(&pTxFrame
->
2892 AmiSetByteToLe(&pTxFrame
->
2899 AmiSetByteToLe(&pTxFrame
->
2909 (&EplDllkInstance_g
.
2911 [EPL_DLLK_TXFRAME_STATUSRES
]);
2912 if (Ret
!= kEplSuccessful
) {
2915 TGT_DBG_SIGNAL_TRACE_POINT(8);
2917 // update error signaling
2919 AmiGetByteFromLe(&pFrame
->
2923 if (((bFlag1
^ EplDllkInstance_g
.m_bMnFlag1
) & EPL_FRAME_FLAG1_ER
) != 0) { // exception reset flag was changed by MN
2924 // assume same state for EC in next cycle (clear all other bits)
2928 // set EC and reset rest
2933 // reset complete flag 1 (including EC and EN)
2939 // save flag 1 from MN for Status request response cycle
2940 EplDllkInstance_g
.m_bMnFlag1
=
2943 } else if (ReqServiceId
== kEplDllReqServiceIdent
) { // IdentRequest
2944 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_IDENTRES
].m_pbBuffer
!= NULL
) { // IdentRes does exist
2949 [EPL_DLLK_TXFRAME_IDENTRES
].
2951 // update IdentRes frame (NMT state, RS, PR flags)
2952 AmiSetByteToLe(&pTxFrame
->
2958 AmiSetByteToLe(&pTxFrame
->
2968 (&EplDllkInstance_g
.
2970 [EPL_DLLK_TXFRAME_IDENTRES
]);
2971 if (Ret
!= kEplSuccessful
) {
2974 TGT_DBG_SIGNAL_TRACE_POINT(7);
2976 } else if (ReqServiceId
== kEplDllReqServiceNmtRequest
) { // NmtRequest
2977 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NMTREQ
].m_pbBuffer
!= NULL
) { // NmtRequest does exist
2978 // check if frame is not empty and not being filled
2979 if (EplDllkInstance_g
.
2981 [EPL_DLLK_TXFRAME_NMTREQ
].
2983 EPL_DLLK_BUFLEN_FILLING
) {
2984 /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
2986 EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
2988 // memorize transmission
2994 (&EplDllkInstance_g
.
2996 [EPL_DLLK_TXFRAME_NMTREQ
]);
3005 } else if (ReqServiceId
== kEplDllReqServiceUnspecified
) { // unspecified invite
3006 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NONEPL
].m_pbBuffer
!= NULL
) { // non-EPL frame does exist
3007 // check if frame is not empty and not being filled
3008 if (EplDllkInstance_g
.
3010 [EPL_DLLK_TXFRAME_NONEPL
].
3012 EPL_DLLK_BUFLEN_FILLING
) {
3013 /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
3015 EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
3017 // memorize transmission
3020 // send non-EPL frame
3023 (&EplDllkInstance_g
.
3025 [EPL_DLLK_TXFRAME_NONEPL
]);
3034 } else if (ReqServiceId
== kEplDllReqServiceNo
) { // no async service requested -> do nothing
3037 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3038 if (pTxFrame
== NULL
) { // signal process function readiness of PRes frame
3039 Event
.m_EventSink
= kEplEventSinkDllk
;
3040 Event
.m_EventType
= kEplEventTypeDllkPresReady
;
3042 Event
.m_pArg
= NULL
;
3043 Ret
= EplEventkPost(&Event
);
3047 // inform PDO module
3048 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
3049 // Ret = EplPdokCbSoa(&FrameInfo);
3052 // $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
3054 // $$$ inform emergency protocol handling about flags
3058 case kEplMsgTypeAsnd
:
3061 NmtEvent
= kEplNmtEventDllCeAsnd
;
3063 // ASnd service registered?
3065 (unsigned int)AmiGetByteFromLe(&pFrame
->m_Data
.
3069 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3070 if ((EplDllkInstance_g
.m_DllState
>= kEplDllMsNonCyclic
)
3072 ((((tEplDllAsndServiceId
) uiAsndServiceId
) ==
3073 kEplDllAsndStatusResponse
)
3074 || (((tEplDllAsndServiceId
) uiAsndServiceId
) == kEplDllAsndIdentResponse
))) { // StatusRes or IdentRes received
3076 AmiGetByteFromLe(&pFrame
->m_le_bSrcNodeId
);
3077 if ((EplDllkInstance_g
.m_LastReqServiceId
==
3078 ((tEplDllReqServiceId
) uiAsndServiceId
))
3079 && (uiNodeId
== EplDllkInstance_g
.m_uiLastTargetNodeId
)) { // mark request as responded
3080 EplDllkInstance_g
.m_LastReqServiceId
=
3081 kEplDllReqServiceNo
;
3083 if (((tEplDllAsndServiceId
) uiAsndServiceId
) == kEplDllAsndIdentResponse
) { // memorize MAC address of CN for PReq
3084 tEplDllkNodeInfo
*pIntNodeInfo
;
3087 EplDllkGetNodeInfo(uiNodeId
);
3088 if (pIntNodeInfo
== NULL
) { // no node info structure available
3089 Ret
= kEplDllNoNodeInfo
;
3091 EPL_MEMCPY(pIntNodeInfo
->
3097 // forward Flag2 to asynchronous scheduler
3099 AmiGetByteFromLe(&pFrame
->m_Data
.m_Asnd
.
3100 m_Payload
.m_StatusResponse
.
3103 EplDllkCalAsyncSetPendingRequests(uiNodeId
,
3104 ((tEplDllAsyncReqPriority
) ((bFlag1
& EPL_FRAME_FLAG2_PR
) >> EPL_FRAME_FLAG2_PR_SHIFT
)), (bFlag1
& EPL_FRAME_FLAG2_RS
));
3108 if (uiAsndServiceId
< EPL_DLL_MAX_ASND_SERVICE_ID
) { // ASnd service ID is valid
3109 if (EplDllkInstance_g
.m_aAsndFilter
[uiAsndServiceId
] == kEplDllAsndFilterAny
) { // ASnd service ID is registered
3110 // forward frame via async receive FIFO to userspace
3112 EplDllkCalAsyncFrameReceived
3114 } else if (EplDllkInstance_g
.m_aAsndFilter
[uiAsndServiceId
] == kEplDllAsndFilterLocal
) { // ASnd service ID is registered, but only local node ID or broadcasts
3115 // shall be forwarded
3117 AmiGetByteFromLe(&pFrame
->
3120 EplDllkInstance_g
.m_DllConfigParam
.
3122 || (uiNodeId
== EPL_C_ADR_BROADCAST
)) { // ASnd frame is intended for us
3123 // forward frame via async receive FIFO to userspace
3125 EplDllkCalAsyncFrameReceived
3139 if (NmtEvent
!= kEplNmtEventNoEvent
) { // event for DLL and NMT state machine generated
3140 Ret
= EplDllkChangeState(NmtEvent
, NmtState
);
3141 if (Ret
!= kEplSuccessful
) {
3145 if ((NmtEvent
!= kEplNmtEventDllCeAsnd
)
3146 && ((NmtState
<= kEplNmtCsPreOperational1
) || (NmtEvent
!= kEplNmtEventDllCePres
))) { // NMT state machine is not interested in ASnd frames and PRes frames when not CsNotActive or CsPreOp1
3147 // inform NMT module
3148 Event
.m_EventSink
= kEplEventSinkNmtk
;
3149 Event
.m_EventType
= kEplEventTypeNmtEvent
;
3150 Event
.m_uiSize
= sizeof(NmtEvent
);
3151 Event
.m_pArg
= &NmtEvent
;
3152 Ret
= EplEventkPost(&Event
);
3157 if (Ret
!= kEplSuccessful
) {
3160 BENCHMARK_MOD_02_TOGGLE(9);
3162 dwArg
= EplDllkInstance_g
.m_DllState
| (NmtEvent
<< 8);
3164 // Error event for API layer
3165 Ret
= EplEventkPostError(kEplEventSourceDllk
,
3166 Ret
, sizeof(dwArg
), &dwArg
);
3168 BENCHMARK_MOD_02_RESET(3);
3172 //---------------------------------------------------------------------------
3174 // Function: EplDllkCbFrameTransmitted()
3176 // Description: called from EdrvInterruptHandler().
3179 // Parameters: pRxBuffer_p = receive buffer structure
3186 //---------------------------------------------------------------------------
3188 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer
* pTxBuffer_p
)
3190 tEplKernel Ret
= kEplSuccessful
;
3192 tEplDllAsyncReqPriority Priority
;
3193 tEplNmtState NmtState
;
3195 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3196 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)
3197 tEplFrameInfo FrameInfo
;
3200 NmtState
= EplNmtkGetNmtState();
3202 if (NmtState
<= kEplNmtGsResetConfiguration
) {
3206 if ((pTxBuffer_p
- EplDllkInstance_g
.m_pTxBuffer
) == EPL_DLLK_TXFRAME_NMTREQ
) { // frame from NMT request FIFO sent
3207 // mark Tx-buffer as empty
3208 pTxBuffer_p
->m_uiTxMsgLen
= EPL_DLLK_BUFLEN_EMPTY
;
3210 // post event to DLL
3211 Priority
= kEplDllAsyncReqPrioNmt
;
3212 Event
.m_EventSink
= kEplEventSinkDllk
;
3213 Event
.m_EventType
= kEplEventTypeDllkFillTx
;
3214 EPL_MEMSET(&Event
.m_NetTime
, 0x00, sizeof(Event
.m_NetTime
));
3215 Event
.m_pArg
= &Priority
;
3216 Event
.m_uiSize
= sizeof(Priority
);
3217 Ret
= EplEventkPost(&Event
);
3218 } else if ((pTxBuffer_p
- EplDllkInstance_g
.m_pTxBuffer
) == EPL_DLLK_TXFRAME_NONEPL
) { // frame from generic priority FIFO sent
3219 // mark Tx-buffer as empty
3220 pTxBuffer_p
->m_uiTxMsgLen
= EPL_DLLK_BUFLEN_EMPTY
;
3222 // post event to DLL
3223 Priority
= kEplDllAsyncReqPrioGeneric
;
3224 Event
.m_EventSink
= kEplEventSinkDllk
;
3225 Event
.m_EventType
= kEplEventTypeDllkFillTx
;
3226 EPL_MEMSET(&Event
.m_NetTime
, 0x00, sizeof(Event
.m_NetTime
));
3227 Event
.m_pArg
= &Priority
;
3228 Event
.m_uiSize
= sizeof(Priority
);
3229 Ret
= EplEventkPost(&Event
);
3231 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3232 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)) \
3233 || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3234 else if ((pTxBuffer_p
->m_EplMsgType
== kEplMsgTypePreq
)
3235 || (pTxBuffer_p
->m_EplMsgType
== kEplMsgTypePres
)) { // PRes resp. PReq frame sent
3237 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3238 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE))
3240 // inform PDO module
3241 FrameInfo
.m_pFrame
=
3242 (tEplFrame
*) pTxBuffer_p
->m_pbBuffer
;
3243 FrameInfo
.m_uiFrameSize
= pTxBuffer_p
->m_uiMaxBufferLen
;
3244 Ret
= EplPdokCbPdoTransmitted(&FrameInfo
);
3248 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3250 // if own Pres on MN, trigger SoA
3251 if ((NmtState
>= kEplNmtMsPreOperational2
)
3254 m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
])) {
3256 EplDllkChangeState(kEplNmtEventDllMeSoaTrig
,
3262 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3267 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3268 else if (pTxBuffer_p
->m_EplMsgType
== kEplMsgTypeSoa
) { // SoA frame sent
3269 tEplNmtEvent NmtEvent
= kEplNmtEventDllMeSoaSent
;
3271 // check if we are invited
3272 if (EplDllkInstance_g
.m_uiLastTargetNodeId
==
3273 EplDllkInstance_g
.m_DllConfigParam
.m_uiNodeId
) {
3274 tEplFrame
*pTxFrame
;
3276 if (EplDllkInstance_g
.m_LastReqServiceId
== kEplDllReqServiceStatus
) { // StatusRequest
3277 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_STATUSRES
].m_pbBuffer
!= NULL
) { // StatusRes does exist
3280 (tEplFrame
*) EplDllkInstance_g
.
3282 [EPL_DLLK_TXFRAME_STATUSRES
].
3284 // update StatusRes frame (NMT state, EN, EC, RS, PR flags)
3285 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.
3290 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.
3296 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.
3304 EdrvSendTxMsg(&EplDllkInstance_g
.
3306 [EPL_DLLK_TXFRAME_STATUSRES
]);
3307 if (Ret
!= kEplSuccessful
) {
3310 TGT_DBG_SIGNAL_TRACE_POINT(8);
3313 } else if (EplDllkInstance_g
.m_LastReqServiceId
== kEplDllReqServiceIdent
) { // IdentRequest
3314 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_IDENTRES
].m_pbBuffer
!= NULL
) { // IdentRes does exist
3316 (tEplFrame
*) EplDllkInstance_g
.
3318 [EPL_DLLK_TXFRAME_IDENTRES
].
3320 // update IdentRes frame (NMT state, RS, PR flags)
3321 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.
3326 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Asnd
.
3334 EdrvSendTxMsg(&EplDllkInstance_g
.
3336 [EPL_DLLK_TXFRAME_IDENTRES
]);
3337 if (Ret
!= kEplSuccessful
) {
3340 TGT_DBG_SIGNAL_TRACE_POINT(7);
3342 } else if (EplDllkInstance_g
.m_LastReqServiceId
== kEplDllReqServiceNmtRequest
) { // NmtRequest
3343 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NMTREQ
].m_pbBuffer
!= NULL
) { // NmtRequest does exist
3344 // check if frame is not empty and not being filled
3345 if (EplDllkInstance_g
.
3347 [EPL_DLLK_TXFRAME_NMTREQ
].
3349 EPL_DLLK_BUFLEN_FILLING
) {
3350 // check if this frame is a NMT command,
3351 // then forward this frame back to NmtMnu module,
3352 // because it needs the time, when this frame is
3353 // actually sent, to start the timer for monitoring
3354 // the NMT state change.
3360 [EPL_DLLK_TXFRAME_NMTREQ
].
3362 if ((AmiGetByteFromLe
3365 == (BYTE
) kEplMsgTypeAsnd
)
3368 (&pTxFrame
->m_Data
.m_Asnd
.
3370 == (BYTE
) kEplDllAsndNmtCommand
)) { // post event directly to NmtMnu module
3372 kEplEventSinkNmtMnu
;
3374 kEplEventTypeNmtMnuNmtCmdSent
;
3378 [EPL_DLLK_TXFRAME_NMTREQ
].
3380 Event
.m_pArg
= pTxFrame
;
3389 (&EplDllkInstance_g
.
3391 [EPL_DLLK_TXFRAME_NMTREQ
]);
3392 if (Ret
!= kEplSuccessful
) {
3399 } else if (EplDllkInstance_g
.m_LastReqServiceId
== kEplDllReqServiceUnspecified
) { // unspecified invite
3400 if (EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_NONEPL
].m_pbBuffer
!= NULL
) { // non-EPL frame does exist
3401 // check if frame is not empty and not being filled
3402 if (EplDllkInstance_g
.
3404 [EPL_DLLK_TXFRAME_NONEPL
].
3406 EPL_DLLK_BUFLEN_FILLING
) {
3407 // send non-EPL frame
3410 (&EplDllkInstance_g
.
3412 [EPL_DLLK_TXFRAME_NONEPL
]);
3413 if (Ret
!= kEplSuccessful
) {
3420 // ASnd frame was sent, remove the request
3421 EplDllkInstance_g
.m_LastReqServiceId
=
3422 kEplDllReqServiceNo
;
3424 // forward event to ErrorHandler and PDO module
3425 Event
.m_EventSink
= kEplEventSinkNmtk
;
3426 Event
.m_EventType
= kEplEventTypeNmtEvent
;
3427 Event
.m_uiSize
= sizeof(NmtEvent
);
3428 Event
.m_pArg
= &NmtEvent
;
3429 Ret
= EplEventkPost(&Event
);
3430 if (Ret
!= kEplSuccessful
) {
3436 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3437 else { // d.k.: Why that else? on CN it is entered on IdentRes and StatusRes
3441 // signal process function readiness of PRes frame
3442 Event
.m_EventSink
= kEplEventSinkDllk
;
3443 Event
.m_EventType
= kEplEventTypeDllkPresReady
;
3445 Event
.m_pArg
= NULL
;
3446 Ret
= EplEventkPost(&Event
);
3451 if (Ret
!= kEplSuccessful
) {
3454 BENCHMARK_MOD_02_TOGGLE(9);
3457 EplDllkInstance_g
.m_DllState
| (pTxBuffer_p
->
3458 m_EplMsgType
<< 16);
3460 // Error event for API layer
3461 Ret
= EplEventkPostError(kEplEventSourceDllk
,
3462 Ret
, sizeof(dwArg
), &dwArg
);
3468 //---------------------------------------------------------------------------
3470 // Function: EplDllkCheckFrame()
3472 // Description: check frame and set missing information
3474 // Parameters: pFrame_p = ethernet frame
3475 // uiFrameSize_p = size of frame
3477 // Returns: tEplKernel = error code
3482 //---------------------------------------------------------------------------
3484 static tEplKernel
EplDllkCheckFrame(tEplFrame
* pFrame_p
,
3485 unsigned int uiFrameSize_p
)
3487 tEplMsgType MsgType
;
3491 if (pFrame_p
!= NULL
) {
3493 if (AmiGetQword48FromBe(pFrame_p
->m_be_abSrcMac
) == 0) {
3494 // source MAC address
3495 EPL_MEMCPY(&pFrame_p
->m_be_abSrcMac
[0],
3496 &EplDllkInstance_g
.m_be_abSrcMac
[0], 6);
3499 wEtherType
= AmiGetWordFromBe(&pFrame_p
->m_be_wEtherType
);
3500 if (wEtherType
== 0) {
3502 wEtherType
= EPL_C_DLL_ETHERTYPE_EPL
;
3503 AmiSetWordToBe(&pFrame_p
->m_be_wEtherType
, wEtherType
);
3506 if (wEtherType
== EPL_C_DLL_ETHERTYPE_EPL
) {
3508 AmiSetByteToLe(&pFrame_p
->m_le_bSrcNodeId
,
3509 (BYTE
) EplDllkInstance_g
.
3510 m_DllConfigParam
.m_uiNodeId
);
3512 // check message type
3514 AmiGetByteFromLe(&pFrame_p
->m_le_bMessageType
);
3516 MsgType
= kEplMsgTypeAsnd
;
3517 AmiSetByteToLe(&pFrame_p
->m_le_bMessageType
,
3521 if (MsgType
== kEplMsgTypeAsnd
) {
3522 // destination MAC address
3523 AmiSetQword48ToBe(&pFrame_p
->m_be_abDstMac
[0],
3524 EPL_C_DLL_MULTICAST_ASND
);
3530 return kEplSuccessful
;
3533 //---------------------------------------------------------------------------
3535 // Function: EplDllkCbCnTimer()
3537 // Description: called by timer module. It monitors the EPL cycle when it is a CN.
3539 // Parameters: pEventArg_p = timer event argument
3541 // Returns: tEplKernel = error code
3546 //---------------------------------------------------------------------------
3548 #if EPL_TIMER_USE_HIGHRES != FALSE
3549 static tEplKernel PUBLIC
EplDllkCbCnTimer(tEplTimerEventArg
* pEventArg_p
)
3551 tEplKernel Ret
= kEplSuccessful
;
3552 tEplNmtState NmtState
;
3554 #if EPL_TIMER_USE_HIGHRES != FALSE
3555 if (pEventArg_p
->m_TimerHdl
!= EplDllkInstance_g
.m_TimerHdlCycle
) { // zombie callback
3561 NmtState
= EplNmtkGetNmtState();
3563 if (NmtState
<= kEplNmtGsResetConfiguration
) {
3567 Ret
= EplDllkChangeState(kEplNmtEventDllCeFrameTimeout
, NmtState
);
3568 if (Ret
!= kEplSuccessful
) {
3571 // 2008/10/15 d.k. reprogramming of timer not necessary,
3572 // because it will be programmed, when SoC is received.
3575 #if EPL_TIMER_USE_HIGHRES != FALSE
3576 if ((NmtState > kEplNmtCsPreOperational1)
3577 && (EplDllkInstance_g.m_ullFrameTimeout != 0))
3579 Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE);
3585 if (Ret
!= kEplSuccessful
) {
3588 BENCHMARK_MOD_02_TOGGLE(9);
3592 m_DllState
| (kEplNmtEventDllCeFrameTimeout
<< 8);
3594 // Error event for API layer
3595 Ret
= EplEventkPostError(kEplEventSourceDllk
,
3596 Ret
, sizeof(dwArg
), &dwArg
);
3603 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3605 //---------------------------------------------------------------------------
3607 // Function: EplDllkCbMnTimerCycle()
3609 // Description: called by timer module. It triggers the SoC when it is a MN.
3611 // Parameters: pEventArg_p = timer event argument
3613 // Returns: tEplKernel = error code
3618 //---------------------------------------------------------------------------
3620 static tEplKernel PUBLIC
EplDllkCbMnTimerCycle(tEplTimerEventArg
* pEventArg_p
)
3622 tEplKernel Ret
= kEplSuccessful
;
3623 tEplNmtState NmtState
;
3625 #if EPL_TIMER_USE_HIGHRES != FALSE
3626 if (pEventArg_p
->m_TimerHdl
!= EplDllkInstance_g
.m_TimerHdlCycle
) { // zombie callback
3632 NmtState
= EplNmtkGetNmtState();
3634 if (NmtState
<= kEplNmtGsResetConfiguration
) {
3638 Ret
= EplDllkChangeState(kEplNmtEventDllMeSocTrig
, NmtState
);
3641 if (Ret
!= kEplSuccessful
) {
3644 BENCHMARK_MOD_02_TOGGLE(9);
3648 m_DllState
| (kEplNmtEventDllMeSocTrig
<< 8);
3650 // Error event for API layer
3651 Ret
= EplEventkPostError(kEplEventSourceDllk
,
3652 Ret
, sizeof(dwArg
), &dwArg
);
3658 //---------------------------------------------------------------------------
3660 // Function: EplDllkCbMnTimerResponse()
3662 // Description: called by timer module. It monitors the PRes timeout.
3664 // Parameters: pEventArg_p = timer event argument
3666 // Returns: tEplKernel = error code
3671 //---------------------------------------------------------------------------
3673 static tEplKernel PUBLIC
EplDllkCbMnTimerResponse(tEplTimerEventArg
*
3676 tEplKernel Ret
= kEplSuccessful
;
3677 tEplNmtState NmtState
;
3679 #if EPL_TIMER_USE_HIGHRES != FALSE
3680 if (pEventArg_p
->m_TimerHdl
!= EplDllkInstance_g
.m_TimerHdlResponse
) { // zombie callback
3686 NmtState
= EplNmtkGetNmtState();
3688 if (NmtState
<= kEplNmtGsResetConfiguration
) {
3692 Ret
= EplDllkChangeState(kEplNmtEventDllMePresTimeout
, NmtState
);
3695 if (Ret
!= kEplSuccessful
) {
3698 BENCHMARK_MOD_02_TOGGLE(9);
3702 m_DllState
| (kEplNmtEventDllMePresTimeout
<< 8);
3704 // Error event for API layer
3705 Ret
= EplEventkPostError(kEplEventSourceDllk
,
3706 Ret
, sizeof(dwArg
), &dwArg
);
3712 //---------------------------------------------------------------------------
3714 // Function: EplDllkGetNodeInfo()
3716 // Description: returns node info structure of the specified node.
3718 // Parameters: uiNodeId_p = node ID
3720 // Returns: tEplDllkNodeInfo* = pointer to internal node info structure
3725 //---------------------------------------------------------------------------
3727 static tEplDllkNodeInfo
*EplDllkGetNodeInfo(unsigned int uiNodeId_p
)
3729 // $$$ d.k.: use hash algorithm to retrieve the appropriate node info structure
3730 // if size of array is less than 254.
3731 uiNodeId_p
--; // node ID starts at 1 but array at 0
3732 if (uiNodeId_p
>= tabentries(EplDllkInstance_g
.m_aNodeInfo
)) {
3735 return &EplDllkInstance_g
.m_aNodeInfo
[uiNodeId_p
];
3739 //---------------------------------------------------------------------------
3741 // Function: EplDllkMnSendSoa()
3743 // Description: it updates and transmits the SoA.
3745 // Parameters: NmtState_p = current NMT state
3746 // pDllStateProposed_p = proposed DLL state
3747 // fEnableInvitation_p = enable invitation for asynchronous phase
3748 // it will be disabled for EPL_C_DLL_PREOP1_START_CYCLES SoAs
3750 // Returns: tEplKernel = error code
3755 //---------------------------------------------------------------------------
3757 static tEplKernel
EplDllkMnSendSoa(tEplNmtState NmtState_p
,
3758 tEplDllState
* pDllStateProposed_p
,
3759 BOOL fEnableInvitation_p
)
3761 tEplKernel Ret
= kEplSuccessful
;
3762 tEdrvTxBuffer
*pTxBuffer
= NULL
;
3763 tEplFrame
*pTxFrame
;
3764 tEplDllkNodeInfo
*pNodeInfo
;
3766 *pDllStateProposed_p
= kEplDllMsNonCyclic
;
3768 pTxBuffer
= &EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_SOA
];
3769 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // SoA does exist
3770 pTxFrame
= (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
3772 if (fEnableInvitation_p
!= FALSE
) { // fetch target of asynchronous phase
3773 if (EplDllkInstance_g
.m_bFlag2
== 0) { // own queues are empty
3774 EplDllkInstance_g
.m_LastReqServiceId
=
3775 kEplDllReqServiceNo
;
3776 } else if (((tEplDllAsyncReqPriority
) (EplDllkInstance_g
.m_bFlag2
>> EPL_FRAME_FLAG2_PR_SHIFT
)) == kEplDllAsyncReqPrioNmt
) { // frames in own NMT request queue available
3777 EplDllkInstance_g
.m_LastReqServiceId
=
3778 kEplDllReqServiceNmtRequest
;
3780 EplDllkInstance_g
.m_LastReqServiceId
=
3781 kEplDllReqServiceUnspecified
;
3784 EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g
.
3787 m_uiLastTargetNodeId
);
3788 if (Ret
!= kEplSuccessful
) {
3791 if (EplDllkInstance_g
.m_LastReqServiceId
!= kEplDllReqServiceNo
) { // asynchronous phase will be assigned to one node
3792 if (EplDllkInstance_g
.m_uiLastTargetNodeId
== EPL_C_ADR_INVALID
) { // exchange invalid node ID with local node ID
3793 EplDllkInstance_g
.m_uiLastTargetNodeId
=
3794 EplDllkInstance_g
.m_DllConfigParam
.
3796 // d.k. DLL state WaitAsndTrig is not helpful;
3797 // so just step over to WaitSocTrig,
3798 // because own ASnd is sent automatically in CbFrameTransmitted() after SoA.
3799 //*pDllStateProposed_p = kEplDllMsWaitAsndTrig;
3800 *pDllStateProposed_p
=
3801 kEplDllMsWaitSocTrig
;
3802 } else { // assignment to CN
3803 *pDllStateProposed_p
=
3808 EplDllkGetNodeInfo(EplDllkInstance_g
.
3809 m_uiLastTargetNodeId
);
3810 if (pNodeInfo
== NULL
) { // no node info structure available
3811 Ret
= kEplDllNoNodeInfo
;
3814 // update frame (EA, ER flags)
3815 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.
3818 m_bSoaFlag1
& (EPL_FRAME_FLAG1_EA
3820 EPL_FRAME_FLAG1_ER
));
3821 } else { // no assignment of asynchronous phase
3822 *pDllStateProposed_p
= kEplDllMsWaitSocTrig
;
3823 EplDllkInstance_g
.m_uiLastTargetNodeId
=
3827 // update frame (target)
3828 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.
3830 (BYTE
) EplDllkInstance_g
.
3831 m_LastReqServiceId
);
3832 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.
3833 m_le_bReqServiceTarget
,
3834 (BYTE
) EplDllkInstance_g
.
3835 m_uiLastTargetNodeId
);
3837 } else { // invite nobody
3838 // update frame (target)
3839 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.
3840 m_le_bReqServiceId
, (BYTE
) 0);
3841 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.
3842 m_le_bReqServiceTarget
, (BYTE
) 0);
3845 // update frame (NMT state)
3846 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Soa
.m_le_bNmtStatus
,
3850 Ret
= EdrvSendTxMsg(pTxBuffer
);
3857 //---------------------------------------------------------------------------
3859 // Function: EplDllkMnSendSoc()
3861 // Description: it updates and transmits the SoA.
3863 // Parameters: (none)
3865 // Returns: tEplKernel = error code
3870 //---------------------------------------------------------------------------
3872 static tEplKernel
EplDllkMnSendSoc(void)
3874 tEplKernel Ret
= kEplSuccessful
;
3875 tEdrvTxBuffer
*pTxBuffer
= NULL
;
3876 tEplFrame
*pTxFrame
;
3879 pTxBuffer
= &EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_SOC
];
3880 if (pTxBuffer
->m_pbBuffer
!= NULL
) { // SoC does exist
3881 pTxFrame
= (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
3883 // $$$ update NetTime
3886 Ret
= EdrvSendTxMsg(pTxBuffer
);
3887 if (Ret
!= kEplSuccessful
) {
3890 // trigger synchronous task
3891 Event
.m_EventSink
= kEplEventSinkSync
;
3892 Event
.m_EventType
= kEplEventTypeSync
;
3894 Ret
= EplEventkPost(&Event
);
3901 //---------------------------------------------------------------------------
3903 // Function: EplDllkMnSendPreq()
3905 // Description: it updates and transmits the PReq for the next isochronous CN
3906 // or own PRes if enabled.
3908 // Parameters: NmtState_p = current NMT state
3909 // pDllStateProposed_p = proposed DLL state
3911 // Returns: tEplKernel = error code
3916 //---------------------------------------------------------------------------
3918 static tEplKernel
EplDllkMnSendPreq(tEplNmtState NmtState_p
,
3919 tEplDllState
* pDllStateProposed_p
)
3921 tEplKernel Ret
= kEplSuccessful
;
3922 tEdrvTxBuffer
*pTxBuffer
= NULL
;
3923 tEplFrame
*pTxFrame
;
3926 if (EplDllkInstance_g
.m_pCurNodeInfo
== NULL
) { // start with first isochronous CN
3927 EplDllkInstance_g
.m_pCurNodeInfo
=
3928 EplDllkInstance_g
.m_pFirstNodeInfo
;
3929 } else { // iterate to next isochronous CN
3930 EplDllkInstance_g
.m_pCurNodeInfo
=
3931 EplDllkInstance_g
.m_pCurNodeInfo
->m_pNextNodeInfo
;
3934 if (EplDllkInstance_g
.m_pCurNodeInfo
== NULL
) { // last isochronous CN reached
3935 Ret
= EplDllkMnSendSoa(NmtState_p
, pDllStateProposed_p
, TRUE
);
3938 pTxBuffer
= EplDllkInstance_g
.m_pCurNodeInfo
->m_pPreqTxBuffer
;
3940 EplDllkInstance_g
.m_pCurNodeInfo
->
3941 m_bSoaFlag1
& EPL_FRAME_FLAG1_EA
;
3942 *pDllStateProposed_p
= kEplDllMsWaitPres
;
3945 // $$$ d.k.: maybe move this call to CbFrameTransmitted(), because the time should run from there
3946 #if EPL_TIMER_USE_HIGHRES != FALSE
3948 EplTimerHighReskModifyTimerNs(&EplDllkInstance_g
.
3953 EplDllkCbMnTimerResponse
, 0L,
3958 if (pTxBuffer
== NULL
) { // PReq does not exist
3959 Ret
= kEplDllTxBufNotReady
;
3963 pTxFrame
= (tEplFrame
*) pTxBuffer
->m_pbBuffer
;
3965 if (pTxFrame
!= NULL
) { // PReq does exist
3966 if (NmtState_p
== kEplNmtMsOperational
) { // leave RD flag untouched
3968 AmiGetByteFromLe(&pTxFrame
->m_Data
.m_Preq
.
3969 m_le_bFlag1
) & EPL_FRAME_FLAG1_RD
;
3972 if (pTxBuffer
== &EplDllkInstance_g
.m_pTxBuffer
[EPL_DLLK_TXFRAME_PRES
]) { // PRes of MN will be sent
3974 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Pres
.m_le_bNmtStatus
,
3976 *pDllStateProposed_p
= kEplDllMsWaitSoaTrig
;
3978 // $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary
3979 // update frame (Flag1)
3980 AmiSetByteToLe(&pTxFrame
->m_Data
.m_Preq
.m_le_bFlag1
, bFlag1
);
3982 // calculate frame size from payload size
3983 pTxBuffer
->m_uiTxMsgLen
=
3984 AmiGetWordFromLe(&pTxFrame
->m_Data
.m_Preq
.m_le_wSize
) + 24;
3987 Ret
= EdrvSendTxMsg(pTxBuffer
);
3989 Ret
= kEplDllTxFrameInvalid
;
3996 //---------------------------------------------------------------------------
3998 // Function: EplDllkAsyncFrameNotReceived()
4000 // Description: passes empty ASnd frame to receive FIFO.
4001 // It will be called only for frames with registered AsndServiceIds
4002 // (only kEplDllAsndFilterAny).
4006 // Returns: tEplKernel = error code
4011 //---------------------------------------------------------------------------
4013 static tEplKernel
EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
4015 unsigned int uiNodeId_p
)
4017 tEplKernel Ret
= kEplSuccessful
;
4019 tEplFrame
*pFrame
= (tEplFrame
*) abBuffer
;
4020 tEplFrameInfo FrameInfo
;
4022 // check if previous SoA invitation was not answered
4023 switch (ReqServiceId_p
) {
4024 case kEplDllReqServiceIdent
:
4025 case kEplDllReqServiceStatus
:
4026 // ASnd service registered?
4027 if (EplDllkInstance_g
.m_aAsndFilter
[ReqServiceId_p
] == kEplDllAsndFilterAny
) { // ASnd service ID is registered
4028 AmiSetByteToLe(&pFrame
->m_le_bSrcNodeId
,
4031 AmiSetByteToLe(&pFrame
->m_le_bMessageType
,
4032 (BYTE
) kEplMsgTypeAsnd
);
4034 AmiSetByteToLe(&pFrame
->m_Data
.m_Asnd
.m_le_bServiceId
,
4035 (BYTE
) ReqServiceId_p
);
4036 // create frame info structure
4037 FrameInfo
.m_pFrame
= pFrame
;
4038 FrameInfo
.m_uiFrameSize
= 18; // empty non existing ASnd frame
4039 // forward frame via async receive FIFO to userspace
4040 Ret
= EplDllkCalAsyncFrameReceived(&FrameInfo
);
4044 // no invitation issued or it was successfully answered or it is uninteresting
4051 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
4053 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)