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 TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
125 void TgtDbgPostTraceValue(u32 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
199 tEdrvTxBuffer *m_pTxBuffer; // Buffers for Tx-Frames
200 unsigned int m_uiMaxTxFrames;
201 u8 m_bFlag1; // Flag 1 with EN, EC for PRes, StatusRes
202 u8 m_bMnFlag1; // Flag 1 with EA, ER from PReq, SoA of MN
203 u8 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 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 EplDllkCbMnTimerCycle(tEplTimerEventArg *pEventArg_p);
283 static tEplKernel EplDllkCbMnTimerResponse(tEplTimerEventArg *pEventArg_p);
287 //=========================================================================//
289 // P U B L I C F U N C T I O N S //
291 //=========================================================================//
293 //---------------------------------------------------------------------------
295 // Function: EplDllkAddInstance()
297 // Description: add and initialize new instance of EPL stack
299 // Parameters: pInitParam_p = initialisation parameters like MAC address
301 // Returns: tEplKernel = error code
306 //---------------------------------------------------------------------------
308 tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)
310 tEplKernel Ret = kEplSuccessful;
311 unsigned int uiIndex;
312 tEdrvInitParam EdrvInitParam;
314 // reset instance structure
315 EPL_MEMSET(&EplDllkInstance_g, 0, sizeof(EplDllkInstance_g));
317 #if EPL_TIMER_USE_HIGHRES != FALSE
318 Ret = EplTimerHighReskInit();
319 if (Ret != kEplSuccessful) { // error occured while initializing high resolution timer module
324 // if dynamic memory allocation available
325 // allocate instance structure
326 // allocate TPDO and RPDO table with default size
328 // initialize and link pointers in instance structure to frame tables
329 EplDllkInstance_g.m_pTxBuffer = aEplDllkTxBuffer_l;
330 EplDllkInstance_g.m_uiMaxTxFrames =
331 sizeof(aEplDllkTxBuffer_l) / sizeof(tEdrvTxBuffer);
334 EplDllkInstance_g.m_DllState = kEplDllGsInit;
336 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
337 // set up node info structure
338 for (uiIndex = 0; uiIndex < tabentries(EplDllkInstance_g.m_aNodeInfo);
340 EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
341 EplDllkInstance_g.m_aNodeInfo[uiIndex].m_wPresPayloadLimit =
347 EPL_MEMCPY(EdrvInitParam.m_abMyMacAddr, pInitParam_p->m_be_abSrcMac, 6);
348 EdrvInitParam.m_pfnRxHandler = EplDllkCbFrameReceived;
349 EdrvInitParam.m_pfnTxHandler = EplDllkCbFrameTransmitted;
350 Ret = EdrvInit(&EdrvInitParam);
351 if (Ret != kEplSuccessful) { // error occured while initializing ethernet driver
354 // copy local MAC address from Ethernet driver back to local instance structure
355 // because Ethernet driver may have read it from controller EEPROM
356 EPL_MEMCPY(EplDllkInstance_g.m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr,
358 EPL_MEMCPY(pInitParam_p->m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6);
360 // initialize TxBuffer array
361 for (uiIndex = 0; uiIndex < EplDllkInstance_g.m_uiMaxTxFrames;
363 EplDllkInstance_g.m_pTxBuffer[uiIndex].m_pbBuffer = NULL;
366 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
367 Ret = VEthAddInstance(pInitParam_p);
374 //---------------------------------------------------------------------------
376 // Function: EplDllkDelInstance()
378 // Description: deletes an instance of EPL stack
380 // Parameters: (none)
382 // Returns: tEplKernel = error code
387 //---------------------------------------------------------------------------
389 tEplKernel EplDllkDelInstance(void)
391 tEplKernel Ret = kEplSuccessful;
394 EplDllkInstance_g.m_DllState = kEplDllGsInit;
396 #if EPL_TIMER_USE_HIGHRES != FALSE
397 Ret = EplTimerHighReskDelInstance();
400 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
401 Ret = VEthDelInstance();
404 Ret = EdrvShutdown();
408 //---------------------------------------------------------------------------
410 // Function: EplDllkCreateTxFrame
412 // Description: creates the buffer for a Tx frame and registers it to the
415 // Parameters: puiHandle_p = OUT: handle to frame buffer
416 // ppFrame_p = OUT: pointer to pointer of EPL frame
417 // puiFrameSize_p = IN/OUT: pointer to size of frame
418 // returned size is always equal or larger than
419 // requested size, if that is not possible
420 // an error will be returned
421 // MsgType_p = EPL message type
422 // ServiceId_p = Service ID in case of ASnd frame, otherwise
423 // kEplDllAsndNotDefined
425 // Returns: tEplKernel = error code
430 //---------------------------------------------------------------------------
432 tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p,
433 tEplFrame ** ppFrame_p,
434 unsigned int *puiFrameSize_p,
435 tEplMsgType MsgType_p,
436 tEplDllAsndServiceId ServiceId_p)
438 tEplKernel Ret = kEplSuccessful;
440 unsigned int uiHandle = EplDllkInstance_g.m_uiMaxTxFrames;
441 tEdrvTxBuffer *pTxBuffer = NULL;
443 if (MsgType_p == kEplMsgTypeAsnd) {
444 // search for fixed Tx buffers
445 if (ServiceId_p == kEplDllAsndIdentResponse) {
446 uiHandle = EPL_DLLK_TXFRAME_IDENTRES;
447 } else if (ServiceId_p == kEplDllAsndStatusResponse) {
448 uiHandle = EPL_DLLK_TXFRAME_STATUSRES;
449 } else if ((ServiceId_p == kEplDllAsndNmtRequest)
450 || (ServiceId_p == kEplDllAsndNmtCommand)) {
451 uiHandle = EPL_DLLK_TXFRAME_NMTREQ;
454 if (uiHandle >= EplDllkInstance_g.m_uiMaxTxFrames) { // look for free entry
455 uiHandle = EPL_DLLK_TXFRAME_PREQ;
456 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
457 for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames;
458 uiHandle++, pTxBuffer++) {
459 if (pTxBuffer->m_pbBuffer == NULL) { // free entry found
464 } else if (MsgType_p == kEplMsgTypeNonEpl) {
465 uiHandle = EPL_DLLK_TXFRAME_NONEPL;
466 } else if (MsgType_p == kEplMsgTypePres) {
467 uiHandle = EPL_DLLK_TXFRAME_PRES;
468 } else if (MsgType_p == kEplMsgTypeSoc) {
469 uiHandle = EPL_DLLK_TXFRAME_SOC;
470 } else if (MsgType_p == kEplMsgTypeSoa) {
471 uiHandle = EPL_DLLK_TXFRAME_SOA;
472 } else { // look for free entry
473 uiHandle = EPL_DLLK_TXFRAME_PREQ;
474 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
475 for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames;
476 uiHandle++, pTxBuffer++) {
477 if (pTxBuffer->m_pbBuffer == NULL) { // free entry found
481 if (pTxBuffer->m_pbBuffer != NULL) {
482 Ret = kEplEdrvNoFreeBufEntry;
487 // test if requested entry is free
488 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
489 if (pTxBuffer->m_pbBuffer != NULL) { // entry is not free
490 Ret = kEplEdrvNoFreeBufEntry;
494 pTxBuffer->m_EplMsgType = MsgType_p;
495 pTxBuffer->m_uiMaxBufferLen = *puiFrameSize_p;
497 Ret = EdrvAllocTxMsgBuffer(pTxBuffer);
498 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
501 // because buffer size may be larger than requested
502 // memorize real length of frame
503 pTxBuffer->m_uiTxMsgLen = *puiFrameSize_p;
505 // fill whole frame with 0
506 EPL_MEMSET(pTxBuffer->m_pbBuffer, 0, pTxBuffer->m_uiMaxBufferLen);
508 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
510 if (MsgType_p != kEplMsgTypeNonEpl) { // fill out Frame only if it is an EPL frame
512 AmiSetWordToBe(&pTxFrame->m_be_wEtherType,
513 EPL_C_DLL_ETHERTYPE_EPL);
515 AmiSetByteToLe(&pTxFrame->m_le_bSrcNodeId,
516 (u8) EplDllkInstance_g.m_DllConfigParam.
518 // source MAC address
519 EPL_MEMCPY(&pTxFrame->m_be_abSrcMac[0],
520 &EplDllkInstance_g.m_be_abSrcMac[0], 6);
522 case kEplMsgTypeAsnd:
523 // destination MAC address
524 AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
525 EPL_C_DLL_MULTICAST_ASND);
526 // destination node ID
527 switch (ServiceId_p) {
528 case kEplDllAsndIdentResponse:
529 case kEplDllAsndStatusResponse:
530 { // IdentResponses and StatusResponses are Broadcast
531 AmiSetByteToLe(&pTxFrame->
534 EPL_C_ADR_BROADCAST);
542 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId,
547 // destination MAC address
548 AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
549 EPL_C_DLL_MULTICAST_SOC);
550 // destination node ID
551 AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
552 (u8) EPL_C_ADR_BROADCAST);
554 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (u8) 0);
555 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (u8) 0);
559 // destination MAC address
560 AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
561 EPL_C_DLL_MULTICAST_SOA);
562 // destination node ID
563 AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
564 (u8) EPL_C_ADR_BROADCAST);
566 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (u8) 0);
567 //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (u8) 0);
568 // EPL profile version
569 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bEplVersion,
570 (u8) EPL_SPEC_VERSION);
573 case kEplMsgTypePres:
574 // destination MAC address
575 AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
576 EPL_C_DLL_MULTICAST_PRES);
577 // destination node ID
578 AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
579 (u8) EPL_C_ADR_BROADCAST);
581 //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (u8) 0);
582 //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (u8) 0);
584 //AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0);
587 case kEplMsgTypePreq:
589 //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (u8) 0);
590 //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (u8) 0);
592 //AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0);
599 AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (u8) MsgType_p);
602 *ppFrame_p = pTxFrame;
603 *puiFrameSize_p = pTxBuffer->m_uiMaxBufferLen;
604 *puiHandle_p = uiHandle;
610 //---------------------------------------------------------------------------
612 // Function: EplDllkDeleteTxFrame
614 // Description: deletes the buffer for a Tx frame and frees it in the
617 // Parameters: uiHandle_p = IN: handle to frame buffer
619 // Returns: tEplKernel = error code
624 //---------------------------------------------------------------------------
626 tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p)
628 tEplKernel Ret = kEplSuccessful;
629 tEdrvTxBuffer *pTxBuffer = NULL;
631 if (uiHandle_p >= EplDllkInstance_g.m_uiMaxTxFrames) { // handle is not valid
632 Ret = kEplDllIllegalHdl;
636 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle_p];
638 // mark buffer as free so that frame will not be send in future anymore
639 // $$$ d.k. What's up with running transmissions?
640 pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
641 pTxBuffer->m_pbBuffer = NULL;
644 Ret = EdrvReleaseTxMsgBuffer(pTxBuffer);
645 if (Ret != kEplSuccessful) { // error occured while releasing Tx frame
653 //---------------------------------------------------------------------------
655 // Function: EplDllkProcess
657 // Description: process the passed event
659 // Parameters: pEvent_p = event to be processed
661 // Returns: tEplKernel = error code
666 //---------------------------------------------------------------------------
668 tEplKernel EplDllkProcess(tEplEvent * pEvent_p)
670 tEplKernel Ret = kEplSuccessful;
672 tEdrvTxBuffer *pTxBuffer;
673 unsigned int uiHandle;
674 unsigned int uiFrameSize;
675 u8 abMulticastMac[6];
676 tEplDllAsyncReqPriority AsyncReqPriority;
677 unsigned int uiFrameCount;
678 tEplNmtState NmtState;
679 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
680 tEplFrameInfo FrameInfo;
683 switch (pEvent_p->m_EventType) {
684 case kEplEventTypeDllkCreate:
686 // $$$ reset ethernet driver
688 NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
690 // initialize flags for PRes and StatusRes
691 EplDllkInstance_g.m_bFlag1 = EPL_FRAME_FLAG1_EC;
692 EplDllkInstance_g.m_bMnFlag1 = 0;
693 EplDllkInstance_g.m_bFlag2 = 0;
695 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
696 // initialize linked node list
697 EplDllkInstance_g.m_pFirstNodeInfo = NULL;
700 // register TxFrames in Edrv
703 uiFrameSize = EPL_C_DLL_MINSIZE_IDENTRES;
705 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
706 &uiFrameSize, kEplMsgTypeAsnd,
707 kEplDllAsndIdentResponse);
708 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
711 // EPL profile version
712 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
713 m_IdentResponse.m_le_bEplProfileVersion,
714 (u8) EPL_SPEC_VERSION);
716 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
717 m_IdentResponse.m_le_dwFeatureFlags,
718 EplDllkInstance_g.m_DllConfigParam.
721 AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
722 m_IdentResponse.m_le_wMtu,
723 (u16) EplDllkInstance_g.
724 m_DllConfigParam.m_uiAsyncMtu);
726 AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
727 m_IdentResponse.m_le_wPollInSize,
728 (u16) EplDllkInstance_g.
730 m_uiPreqActPayloadLimit);
732 AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
733 m_IdentResponse.m_le_wPollOutSize,
734 (u16) EplDllkInstance_g.
736 m_uiPresActPayloadLimit);
737 // ResponseTime / PresMaxLatency
738 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
739 m_IdentResponse.m_le_dwResponseTime,
740 EplDllkInstance_g.m_DllConfigParam.
743 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
744 m_IdentResponse.m_le_dwDeviceType,
745 EplDllkInstance_g.m_DllIdentParam.
748 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
749 m_IdentResponse.m_le_dwVendorId,
750 EplDllkInstance_g.m_DllIdentParam.
753 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
754 m_IdentResponse.m_le_dwProductCode,
755 EplDllkInstance_g.m_DllIdentParam.
758 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
759 m_IdentResponse.m_le_dwRevisionNumber,
760 EplDllkInstance_g.m_DllIdentParam.
763 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
764 m_IdentResponse.m_le_dwSerialNumber,
765 EplDllkInstance_g.m_DllIdentParam.
767 // VendorSpecificExt1
768 AmiSetQword64ToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
770 m_le_qwVendorSpecificExt1,
771 EplDllkInstance_g.m_DllIdentParam.
772 m_qwVendorSpecificExt1);
773 // VerifyConfigurationDate
774 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
776 m_le_dwVerifyConfigurationDate,
777 EplDllkInstance_g.m_DllIdentParam.
778 m_dwVerifyConfigurationDate);
779 // VerifyConfigurationTime
780 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
782 m_le_dwVerifyConfigurationTime,
783 EplDllkInstance_g.m_DllIdentParam.
784 m_dwVerifyConfigurationTime);
786 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
788 m_le_dwApplicationSwDate,
789 EplDllkInstance_g.m_DllIdentParam.
790 m_dwApplicationSwDate);
792 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
794 m_le_dwApplicationSwTime,
795 EplDllkInstance_g.m_DllIdentParam.
796 m_dwApplicationSwTime);
798 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
799 m_IdentResponse.m_le_dwIpAddress,
800 EplDllkInstance_g.m_DllIdentParam.
803 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
804 m_IdentResponse.m_le_dwSubnetMask,
805 EplDllkInstance_g.m_DllIdentParam.
808 AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
809 m_IdentResponse.m_le_dwDefaultGateway,
810 EplDllkInstance_g.m_DllIdentParam.
813 EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.
814 m_IdentResponse.m_le_sHostname[0],
815 &EplDllkInstance_g.m_DllIdentParam.
817 sizeof(EplDllkInstance_g.m_DllIdentParam.
819 // VendorSpecificExt2
820 EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.
821 m_IdentResponse.m_le_abVendorSpecificExt2[0],
822 &EplDllkInstance_g.m_DllIdentParam.
823 m_abVendorSpecificExt2[0],
824 sizeof(EplDllkInstance_g.m_DllIdentParam.
825 m_abVendorSpecificExt2));
828 uiFrameSize = EPL_C_DLL_MINSIZE_STATUSRES;
830 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
831 &uiFrameSize, kEplMsgTypeAsnd,
832 kEplDllAsndStatusResponse);
833 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
836 // PRes $$$ maybe move this to PDO module
837 if ((EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly ==
839 && (EplDllkInstance_g.m_DllConfigParam.m_uiPresActPayloadLimit >= 36)) { // it is not configured as async-only CN,
840 // so take part in isochronous phase and register PRes frame
842 EplDllkInstance_g.m_DllConfigParam.
843 m_uiPresActPayloadLimit + 24;
845 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
848 kEplDllAsndNotDefined);
849 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
852 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
853 // initially encode TPDO -> inform PDO module
854 FrameInfo.m_pFrame = pTxFrame;
855 FrameInfo.m_uiFrameSize = uiFrameSize;
856 Ret = EplPdokCbPdoTransmitted(&FrameInfo);
858 // reset cycle counter
859 EplDllkInstance_g.m_uiCycleCount = 0;
860 } else { // it is an async-only CN
861 // fool EplDllkChangeState() to think that PRes was not expected
862 EplDllkInstance_g.m_uiCycleCount = 1;
866 uiFrameSize = EPL_C_IP_MAX_MTU;
868 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
869 &uiFrameSize, kEplMsgTypeAsnd,
870 kEplDllAsndNmtRequest);
871 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
874 // mark Tx buffer as empty
875 EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
876 EPL_DLLK_BUFLEN_EMPTY;
879 uiFrameSize = EPL_C_IP_MAX_MTU;
881 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
884 kEplDllAsndNotDefined);
885 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
888 // mark Tx buffer as empty
889 EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
890 EPL_DLLK_BUFLEN_EMPTY;
892 // register multicast MACs in ethernet driver
893 AmiSetQword48ToBe(&abMulticastMac[0],
894 EPL_C_DLL_MULTICAST_SOC);
895 Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
896 AmiSetQword48ToBe(&abMulticastMac[0],
897 EPL_C_DLL_MULTICAST_SOA);
898 Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
899 AmiSetQword48ToBe(&abMulticastMac[0],
900 EPL_C_DLL_MULTICAST_PRES);
901 Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
902 AmiSetQword48ToBe(&abMulticastMac[0],
903 EPL_C_DLL_MULTICAST_ASND);
904 Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
906 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
907 if (NmtState >= kEplNmtMsNotActive) { // local node is MN
908 unsigned int uiIndex;
911 uiFrameSize = EPL_C_DLL_MINSIZE_SOC;
913 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
916 kEplDllAsndNotDefined);
917 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
921 uiFrameSize = EPL_C_DLL_MINSIZE_SOA;
923 EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
926 kEplDllAsndNotDefined);
927 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
933 tabentries(EplDllkInstance_g.m_aNodeInfo);
935 // EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
936 EplDllkInstance_g.m_aNodeInfo[uiIndex].
937 m_wPresPayloadLimit =
938 (u16) EplDllkInstance_g.
940 m_uiIsochrRxMaxPayload;
943 // calculate cycle length
944 EplDllkInstance_g.m_ullFrameTimeout = 1000LL
946 ((unsigned long long)EplDllkInstance_g.
947 m_DllConfigParam.m_dwCycleLen);
949 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
951 Ret = EplDllkCalAsyncClearBuffer();
956 case kEplEventTypeDllkDestroy:
958 // destroy all data structures
960 NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
963 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES);
964 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
968 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES);
969 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
973 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES);
974 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
978 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ);
979 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
983 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL);
984 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
987 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
988 if (NmtState >= kEplNmtMsNotActive) { // local node was MN
989 unsigned int uiIndex;
992 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC);
993 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
998 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA);
999 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
1005 tabentries(EplDllkInstance_g.m_aNodeInfo);
1007 if (EplDllkInstance_g.
1008 m_aNodeInfo[uiIndex].
1009 m_pPreqTxBuffer != NULL) {
1012 m_aNodeInfo[uiIndex].
1017 m_aNodeInfo[uiIndex].
1018 m_pPreqTxBuffer = NULL;
1020 EplDllkDeleteTxFrame
1022 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
1027 EplDllkInstance_g.m_aNodeInfo[uiIndex].
1028 m_wPresPayloadLimit = 0xFFFF;
1031 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1033 // deregister multicast MACs in ethernet driver
1034 AmiSetQword48ToBe(&abMulticastMac[0],
1035 EPL_C_DLL_MULTICAST_SOC);
1036 Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1037 AmiSetQword48ToBe(&abMulticastMac[0],
1038 EPL_C_DLL_MULTICAST_SOA);
1039 Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1040 AmiSetQword48ToBe(&abMulticastMac[0],
1041 EPL_C_DLL_MULTICAST_PRES);
1042 Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1043 AmiSetQword48ToBe(&abMulticastMac[0],
1044 EPL_C_DLL_MULTICAST_ASND);
1045 Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1048 #if EPL_TIMER_USE_HIGHRES != FALSE
1050 EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
1057 case kEplEventTypeDllkFillTx:
1059 // fill TxBuffer of specified priority with new frame if empty
1063 *((tEplDllAsyncReqPriority *) pEvent_p->m_pArg);
1064 switch (AsyncReqPriority) {
1065 case kEplDllAsyncReqPrioNmt: // NMT request priority
1070 [EPL_DLLK_TXFRAME_NMTREQ];
1071 if (pTxBuffer->m_pbBuffer != NULL) { // NmtRequest does exist
1072 // check if frame is empty and not being filled
1073 if (pTxBuffer->m_uiTxMsgLen ==
1074 EPL_DLLK_BUFLEN_EMPTY) {
1075 // mark Tx buffer as filling is in process
1078 EPL_DLLK_BUFLEN_FILLING;
1079 // set max buffer size as input parameter
1083 // copy frame from shared loop buffer to Tx buffer
1085 EplDllkCalAsyncGetTxFrame
1107 } else if (Ret == kEplDllAsyncTxBufferEmpty) { // empty Tx buffer is not a real problem
1108 // so just ignore it
1111 // mark Tx buffer as empty
1115 EPL_DLLK_BUFLEN_EMPTY;
1122 default: // generic priority
1127 [EPL_DLLK_TXFRAME_NONEPL];
1128 if (pTxBuffer->m_pbBuffer != NULL) { // non-EPL frame does exist
1129 // check if frame is empty and not being filled
1130 if (pTxBuffer->m_uiTxMsgLen ==
1131 EPL_DLLK_BUFLEN_EMPTY) {
1132 // mark Tx buffer as filling is in process
1135 EPL_DLLK_BUFLEN_FILLING;
1136 // set max buffer size as input parameter
1140 // copy frame from shared loop buffer to Tx buffer
1142 EplDllkCalAsyncGetTxFrame
1164 } else if (Ret == kEplDllAsyncTxBufferEmpty) { // empty Tx buffer is not a real problem
1165 // so just ignore it
1168 // mark Tx buffer as empty
1172 EPL_DLLK_BUFLEN_EMPTY;
1180 NmtState = EplNmtkGetNmtState();
1182 if ((NmtState == kEplNmtCsBasicEthernet) || (NmtState == kEplNmtMsBasicEthernet)) { // send frame immediately
1183 if (pTxFrame != NULL) { // frame is present
1184 // padding is done by Edrv or ethernet controller
1185 Ret = EdrvSendTxMsg(pTxBuffer);
1186 } else { // no frame moved to TxBuffer
1187 // check if TxBuffers contain unsent frames
1188 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // NMT request Tx buffer contains a frame
1191 (&EplDllkInstance_g.
1193 [EPL_DLLK_TXFRAME_NMTREQ]);
1194 } else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // non-EPL Tx buffer contains a frame
1197 (&EplDllkInstance_g.
1199 [EPL_DLLK_TXFRAME_NONEPL]);
1201 if (Ret == kEplInvalidOperation) { // ignore error if caused by already active transmission
1202 Ret = kEplSuccessful;
1205 // reset PRes flag 2
1206 EplDllkInstance_g.m_bFlag2 = 0;
1208 // update Flag 2 (PR, RS)
1210 EplDllkCalAsyncGetTxCount(&AsyncReqPriority,
1212 if (AsyncReqPriority == kEplDllAsyncReqPrioNmt) { // non-empty FIFO with hightest priority is for NMT requests
1213 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // NMT request Tx buffer contains a frame
1214 // add one more frame
1217 } else { // non-empty FIFO with highest priority is for generic frames
1218 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // NMT request Tx buffer contains a frame
1219 // use NMT request FIFO, because of higher priority
1222 kEplDllAsyncReqPrioNmt;
1223 } else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // non-EPL Tx buffer contains a frame
1224 // use NMT request FIFO, because of higher priority
1225 // add one more frame
1230 if (uiFrameCount > 7) { // limit frame request to send counter to 7
1233 if (uiFrameCount > 0) {
1234 EplDllkInstance_g.m_bFlag2 =
1235 (u8) (((AsyncReqPriority <<
1236 EPL_FRAME_FLAG2_PR_SHIFT)
1237 & EPL_FRAME_FLAG2_PR)
1239 EPL_FRAME_FLAG2_RS));
1241 EplDllkInstance_g.m_bFlag2 = 0;
1248 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1249 case kEplEventTypeDllkStartReducedCycle:
1251 // start the reduced cycle by programming the cycle timer
1252 // it is issued by NMT MN module, when PreOp1 is entered
1254 // clear the asynchronous queues
1255 Ret = EplDllkCalAsyncClearQueues();
1257 // reset cycle counter (everytime a SoA is triggerd in PreOp1 the counter is incremented
1258 // and when it reaches EPL_C_DLL_PREOP1_START_CYCLES the SoA may contain invitations)
1259 EplDllkInstance_g.m_uiCycleCount = 0;
1261 // remove any CN from isochronous phase
1262 while (EplDllkInstance_g.m_pFirstNodeInfo != NULL) {
1263 EplDllkDeleteNode(EplDllkInstance_g.
1264 m_pFirstNodeInfo->m_uiNodeId);
1267 // change state to NonCyclic,
1268 // hence EplDllkChangeState() will not ignore the next call
1269 EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
1271 #if EPL_TIMER_USE_HIGHRES != FALSE
1272 if (EplDllkInstance_g.m_DllConfigParam.
1273 m_dwAsyncSlotTimeout != 0) {
1275 EplTimerHighReskModifyTimerNs
1276 (&EplDllkInstance_g.m_TimerHdlCycle,
1277 EplDllkInstance_g.m_DllConfigParam.
1278 m_dwAsyncSlotTimeout,
1279 EplDllkCbMnTimerCycle, 0L, FALSE);
1287 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
1288 case kEplEventTypeDllkPresReady:
1290 // post PRes to transmit FIFO
1292 NmtState = EplNmtkGetNmtState();
1294 if (NmtState != kEplNmtCsBasicEthernet) {
1296 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].m_pbBuffer != NULL) { // PRes does exist
1298 (tEplFrame *) EplDllkInstance_g.
1299 m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].
1301 // update frame (NMT state, RD, RS, PR, MS, EN flags)
1302 if (NmtState < kEplNmtCsPreOperational2) { // NMT state is not PreOp2, ReadyToOp or Op
1303 // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
1305 kEplNmtCsPreOperational2;
1307 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
1310 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
1314 if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
1315 // $$$ reset only RD flag; set other flags appropriately
1316 AmiSetByteToLe(&pTxFrame->
1320 // $$$ make function that updates Pres, StatusRes
1321 // mark PRes frame as ready for transmission
1323 EdrvTxMsgReady(&EplDllkInstance_g.
1325 [EPL_DLLK_TXFRAME_PRES]);
1335 "EplDllkProcess(): unhandled event type!\n");
1343 //---------------------------------------------------------------------------
1345 // Function: EplDllkConfig
1347 // Description: configure parameters of DLL
1349 // Parameters: pDllConfigParam_p = configuration parameters
1351 // Returns: tEplKernel = error code
1356 //---------------------------------------------------------------------------
1358 tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p)
1360 tEplKernel Ret = kEplSuccessful;
1362 // d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
1363 /*tEplNmtState NmtState;
1365 NmtState = EplNmtkGetNmtState();
1367 if (NmtState > kEplNmtGsResetConfiguration)
1368 { // only allowed in state DLL_GS_INIT
1369 Ret = kEplInvalidOperation;
1373 EPL_MEMCPY(&EplDllkInstance_g.m_DllConfigParam, pDllConfigParam_p,
1374 (pDllConfigParam_p->m_uiSizeOfStruct <
1375 sizeof(tEplDllConfigParam) ? pDllConfigParam_p->
1376 m_uiSizeOfStruct : sizeof(tEplDllConfigParam)));
1378 if ((EplDllkInstance_g.m_DllConfigParam.m_dwCycleLen != 0)
1379 && (EplDllkInstance_g.m_DllConfigParam.m_dwLossOfFrameTolerance != 0)) { // monitor EPL cycle, calculate frame timeout
1380 EplDllkInstance_g.m_ullFrameTimeout = (1000LL
1382 ((unsigned long long)
1387 ((unsigned long long)EplDllkInstance_g.m_DllConfigParam.
1388 m_dwLossOfFrameTolerance);
1390 EplDllkInstance_g.m_ullFrameTimeout = 0LL;
1393 if (EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly != FALSE) { // it is configured as async-only CN
1394 // disable multiplexed cycle, that m_uiCycleCount will not be incremented spuriously on SoC
1395 EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt = 0;
1401 //---------------------------------------------------------------------------
1403 // Function: EplDllkSetIdentity
1405 // Description: configure identity of local node for IdentResponse
1407 // Parameters: pDllIdentParam_p = identity
1409 // Returns: tEplKernel = error code
1414 //---------------------------------------------------------------------------
1416 tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p)
1418 tEplKernel Ret = kEplSuccessful;
1420 EPL_MEMCPY(&EplDllkInstance_g.m_DllIdentParam, pDllIdentParam_p,
1421 (pDllIdentParam_p->m_uiSizeOfStruct <
1422 sizeof(tEplDllIdentParam) ? pDllIdentParam_p->
1423 m_uiSizeOfStruct : sizeof(tEplDllIdentParam)));
1425 // $$$ if IdentResponse frame exists update it
1430 //---------------------------------------------------------------------------
1432 // Function: EplDllkRegAsyncHandler
1434 // Description: registers handler for non-EPL frames
1436 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1438 // Returns: tEplKernel = error code
1443 //---------------------------------------------------------------------------
1445 tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1447 tEplKernel Ret = kEplSuccessful;
1449 if (EplDllkInstance_g.m_pfnCbAsync == NULL) { // no handler registered yet
1450 EplDllkInstance_g.m_pfnCbAsync = pfnDllkCbAsync_p;
1451 } else { // handler already registered
1452 Ret = kEplDllCbAsyncRegistered;
1458 //---------------------------------------------------------------------------
1460 // Function: EplDllkDeregAsyncHandler
1462 // Description: deregisters handler for non-EPL frames
1464 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1466 // Returns: tEplKernel = error code
1471 //---------------------------------------------------------------------------
1473 tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1475 tEplKernel Ret = kEplSuccessful;
1477 if (EplDllkInstance_g.m_pfnCbAsync == pfnDllkCbAsync_p) { // same handler is registered
1479 EplDllkInstance_g.m_pfnCbAsync = NULL;
1480 } else { // wrong handler or no handler registered
1481 Ret = kEplDllCbAsyncRegistered;
1487 //---------------------------------------------------------------------------
1489 // Function: EplDllkSetAsndServiceIdFilter()
1491 // Description: sets the specified node ID filter for the specified
1492 // AsndServiceId. It registers C_DLL_MULTICAST_ASND in ethernet
1493 // driver if any AsndServiceId is open.
1495 // Parameters: ServiceId_p = ASnd Service ID
1496 // Filter_p = node ID filter
1498 // Returns: tEplKernel = error code
1503 //---------------------------------------------------------------------------
1505 tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,
1506 tEplDllAsndFilter Filter_p)
1508 tEplKernel Ret = kEplSuccessful;
1510 if (ServiceId_p < tabentries(EplDllkInstance_g.m_aAsndFilter)) {
1511 EplDllkInstance_g.m_aAsndFilter[ServiceId_p] = Filter_p;
1517 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1519 //---------------------------------------------------------------------------
1521 // Function: EplDllkSetFlag1OfNode()
1523 // Description: sets Flag1 (for PReq and SoA) of the specified node ID.
1525 // Parameters: uiNodeId_p = node ID
1526 // bSoaFlag1_p = flag1
1528 // Returns: tEplKernel = error code
1533 //---------------------------------------------------------------------------
1535 tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, u8 bSoaFlag1_p)
1537 tEplKernel Ret = kEplSuccessful;
1538 tEplDllkNodeInfo *pNodeInfo;
1540 pNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1541 if (pNodeInfo == NULL) { // no node info structure available
1542 Ret = kEplDllNoNodeInfo;
1545 // store flag1 in internal node info structure
1546 pNodeInfo->m_bSoaFlag1 = bSoaFlag1_p;
1552 //---------------------------------------------------------------------------
1554 // Function: EplDllkGetFirstNodeInfo()
1556 // Description: returns first info structure of first node in isochronous phase.
1557 // It is only useful for ErrorHandlerk module.
1559 // Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure
1561 // Returns: tEplKernel = error code
1566 //---------------------------------------------------------------------------
1568 tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p)
1570 tEplKernel Ret = kEplSuccessful;
1572 *ppNodeInfo_p = EplDllkInstance_g.m_pFirstNodeInfo;
1577 //---------------------------------------------------------------------------
1579 // Function: EplDllkAddNode()
1581 // Description: adds the specified node to the isochronous phase.
1583 // Parameters: pNodeInfo_p = pointer of node info structure
1585 // Returns: tEplKernel = error code
1590 //---------------------------------------------------------------------------
1592 tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p)
1594 tEplKernel Ret = kEplSuccessful;
1595 tEplDllkNodeInfo *pIntNodeInfo;
1596 tEplDllkNodeInfo **ppIntNodeInfo;
1597 unsigned int uiHandle;
1599 unsigned int uiFrameSize;
1601 pIntNodeInfo = EplDllkGetNodeInfo(pNodeInfo_p->m_uiNodeId);
1602 if (pIntNodeInfo == NULL) { // no node info structure available
1603 Ret = kEplDllNoNodeInfo;
1607 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode,
1608 pNodeInfo_p->m_uiNodeId, 0);
1610 // copy node configuration
1611 pIntNodeInfo->m_dwPresTimeout = pNodeInfo_p->m_dwPresTimeout;
1612 pIntNodeInfo->m_wPresPayloadLimit = pNodeInfo_p->m_wPresPayloadLimit;
1614 // $$$ d.k.: actually add node only if MN. On CN it is sufficient to update the node configuration
1615 if (pNodeInfo_p->m_uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) { // we shall send PRes ourself
1616 // insert our node at the end of the list
1617 ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
1618 while ((*ppIntNodeInfo != NULL)
1619 && ((*ppIntNodeInfo)->m_pNextNodeInfo != NULL)) {
1620 ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
1622 if (*ppIntNodeInfo != NULL) {
1623 if ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId) { // node was already added to list
1624 // $$$ d.k. maybe this should be an error
1626 } else { // add our node at the end of the list
1628 &(*ppIntNodeInfo)->m_pNextNodeInfo;
1631 // set "PReq"-TxBuffer to PRes-TxBuffer
1632 pIntNodeInfo->m_pPreqTxBuffer =
1633 &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
1634 } else { // normal CN shall be added to isochronous phase
1635 // insert node into list in ascending order
1636 ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
1637 while ((*ppIntNodeInfo != NULL)
1638 && ((*ppIntNodeInfo)->m_uiNodeId <
1639 pNodeInfo_p->m_uiNodeId)
1640 && ((*ppIntNodeInfo)->m_uiNodeId !=
1641 EplDllkInstance_g.m_DllConfigParam.m_uiNodeId)) {
1642 ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
1644 if ((*ppIntNodeInfo != NULL) && ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId)) { // node was already added to list
1645 // $$$ d.k. maybe this should be an error
1650 // initialize elements of internal node info structure
1651 pIntNodeInfo->m_bSoaFlag1 = 0;
1652 pIntNodeInfo->m_fSoftDelete = FALSE;
1653 pIntNodeInfo->m_NmtState = kEplNmtCsNotActive;
1654 if (pIntNodeInfo->m_pPreqTxBuffer == NULL) { // create TxBuffer entry
1655 uiFrameSize = pNodeInfo_p->m_wPreqPayloadLimit + 24;
1657 EplDllkCreateTxFrame(&uiHandle, &pFrame, &uiFrameSize,
1659 kEplDllAsndNotDefined);
1660 if (Ret != kEplSuccessful) {
1663 pIntNodeInfo->m_pPreqTxBuffer =
1664 &EplDllkInstance_g.m_pTxBuffer[uiHandle];
1665 AmiSetByteToLe(&pFrame->m_le_bDstNodeId,
1666 (u8) pNodeInfo_p->m_uiNodeId);
1668 // set up destination MAC address
1669 EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr,
1672 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
1674 tEplFrameInfo FrameInfo;
1676 // initially encode TPDO -> inform PDO module
1677 FrameInfo.m_pFrame = pFrame;
1678 FrameInfo.m_uiFrameSize = uiFrameSize;
1679 Ret = EplPdokCbPdoTransmitted(&FrameInfo);
1683 pIntNodeInfo->m_ulDllErrorEvents = 0L;
1685 pIntNodeInfo->m_pNextNodeInfo = *ppIntNodeInfo;
1686 *ppIntNodeInfo = pIntNodeInfo;
1692 //---------------------------------------------------------------------------
1694 // Function: EplDllkDeleteNode()
1696 // Description: removes the specified node from the isochronous phase.
1698 // Parameters: uiNodeId_p = node ID
1700 // Returns: tEplKernel = error code
1705 //---------------------------------------------------------------------------
1707 tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p)
1709 tEplKernel Ret = kEplSuccessful;
1710 tEplDllkNodeInfo *pIntNodeInfo;
1711 tEplDllkNodeInfo **ppIntNodeInfo;
1712 unsigned int uiHandle;
1714 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1715 if (pIntNodeInfo == NULL) { // no node info structure available
1716 Ret = kEplDllNoNodeInfo;
1720 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode, uiNodeId_p, 0);
1722 // search node in whole list
1723 ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
1724 while ((*ppIntNodeInfo != NULL)
1725 && ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) {
1726 ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
1728 if ((*ppIntNodeInfo == NULL) || ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) { // node was not found in list
1729 // $$$ d.k. maybe this should be an error
1732 // remove node from list
1733 *ppIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo;
1735 if ((pIntNodeInfo->m_pPreqTxBuffer != NULL)
1736 && (pIntNodeInfo->m_pPreqTxBuffer != &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) { // delete TxBuffer entry
1738 pIntNodeInfo->m_pPreqTxBuffer -
1739 EplDllkInstance_g.m_pTxBuffer;
1740 pIntNodeInfo->m_pPreqTxBuffer = NULL;
1741 Ret = EplDllkDeleteTxFrame(uiHandle);
1742 /* if (Ret != kEplSuccessful)
1752 //---------------------------------------------------------------------------
1754 // Function: EplDllkSoftDeleteNode()
1756 // Description: removes the specified node not immediately from the isochronous phase.
1757 // Instead the will be removed after error (late/loss PRes) without
1758 // charging the error.
1760 // Parameters: uiNodeId_p = node ID
1762 // Returns: tEplKernel = error code
1767 //---------------------------------------------------------------------------
1769 tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p)
1771 tEplKernel Ret = kEplSuccessful;
1772 tEplDllkNodeInfo *pIntNodeInfo;
1774 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1775 if (pIntNodeInfo == NULL) { // no node info structure available
1776 Ret = kEplDllNoNodeInfo;
1780 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode,
1783 pIntNodeInfo->m_fSoftDelete = TRUE;
1789 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1791 //=========================================================================//
1793 // P R I V A T E F U N C T I O N S //
1795 //=========================================================================//
1797 //---------------------------------------------------------------------------
1799 // Function: EplDllkChangeState
1801 // Description: change DLL state on event and diagnose some communication errors
1803 // Parameters: NmtEvent_p = DLL event (wrapped in NMT event)
1805 // Returns: tEplKernel = error code
1810 //---------------------------------------------------------------------------
1812 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
1813 tEplNmtState NmtState_p)
1815 tEplKernel Ret = kEplSuccessful;
1817 tEplErrorHandlerkEvent DllEvent;
1819 DllEvent.m_ulDllErrorEvents = 0;
1820 DllEvent.m_uiNodeId = 0;
1821 DllEvent.m_NmtState = NmtState_p;
1823 switch (NmtState_p) {
1825 case kEplNmtGsInitialising:
1826 case kEplNmtGsResetApplication:
1827 case kEplNmtGsResetCommunication:
1828 case kEplNmtGsResetConfiguration:
1829 case kEplNmtCsBasicEthernet:
1830 // enter DLL_GS_INIT
1831 EplDllkInstance_g.m_DllState = kEplDllGsInit;
1834 case kEplNmtCsNotActive:
1835 case kEplNmtCsPreOperational1:
1836 // reduced EPL cycle is active
1837 if (NmtEvent_p == kEplNmtEventDllCeSoc) { // SoC received
1838 // enter DLL_CS_WAIT_PREQ
1839 EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
1841 // enter DLL_GS_INIT
1842 EplDllkInstance_g.m_DllState = kEplDllGsInit;
1846 case kEplNmtCsPreOperational2:
1847 case kEplNmtCsReadyToOperate:
1848 case kEplNmtCsOperational:
1849 // full EPL cycle is active
1851 switch (EplDllkInstance_g.m_DllState) {
1852 case kEplDllCsWaitPreq:
1853 switch (NmtEvent_p) {
1855 case kEplNmtEventDllCePreq:
1856 // enter DLL_CS_WAIT_SOA
1857 DllEvent.m_ulDllErrorEvents |=
1858 EPL_DLL_ERR_CN_RECVD_PREQ;
1859 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
1863 case kEplNmtEventDllCeFrameTimeout:
1864 if (NmtState_p == kEplNmtCsPreOperational2) { // ignore frame timeout in PreOp2,
1865 // because the previously configured cycle len
1867 // 2008/10/15 d.k. If it would not be ignored,
1868 // we would go cyclically to PreOp1 and on next
1869 // SoC back to PreOp2.
1872 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
1873 DllEvent.m_ulDllErrorEvents |=
1874 EPL_DLL_ERR_CN_LOSS_SOA |
1875 EPL_DLL_ERR_CN_LOSS_SOC;
1877 // enter DLL_CS_WAIT_SOC
1878 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1881 case kEplNmtEventDllCeSoa:
1882 // check if multiplexed and PReq should have been received in this cycle
1883 // and if >= NMT_CS_READY_TO_OPERATE
1884 if ((EplDllkInstance_g.m_uiCycleCount == 0)
1885 && (NmtState_p >= kEplNmtCsReadyToOperate)) { // report DLL_CEV_LOSS_OF_PREQ
1886 DllEvent.m_ulDllErrorEvents |=
1887 EPL_DLL_ERR_CN_LOSS_PREQ;
1889 // enter DLL_CS_WAIT_SOC
1890 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1894 case kEplNmtEventDllCeSoc:
1895 case kEplNmtEventDllCeAsnd:
1896 // report DLL_CEV_LOSS_SOA
1897 DllEvent.m_ulDllErrorEvents |=
1898 EPL_DLL_ERR_CN_LOSS_SOA;
1900 case kEplNmtEventDllCePres:
1902 // remain in this state
1907 case kEplDllCsWaitSoc:
1908 switch (NmtEvent_p) {
1910 case kEplNmtEventDllCeSoc:
1911 // start of cycle and isochronous phase
1912 // enter DLL_CS_WAIT_PREQ
1913 EplDllkInstance_g.m_DllState =
1918 // case kEplNmtEventDllCePres:
1919 case kEplNmtEventDllCeFrameTimeout:
1920 if (NmtState_p == kEplNmtCsPreOperational2) { // ignore frame timeout in PreOp2,
1921 // because the previously configured cycle len
1923 // 2008/10/15 d.k. If it would not be ignored,
1924 // we would go cyclically to PreOp1 and on next
1925 // SoC back to PreOp2.
1930 case kEplNmtEventDllCePreq:
1931 case kEplNmtEventDllCeSoa:
1932 // report DLL_CEV_LOSS_SOC
1933 DllEvent.m_ulDllErrorEvents |=
1934 EPL_DLL_ERR_CN_LOSS_SOC;
1936 case kEplNmtEventDllCeAsnd:
1938 // remain in this state
1943 case kEplDllCsWaitSoa:
1944 switch (NmtEvent_p) {
1945 case kEplNmtEventDllCeFrameTimeout:
1947 if (NmtState_p == kEplNmtCsPreOperational2) { // ignore frame timeout in PreOp2,
1948 // because the previously configured cycle len
1950 // 2008/10/15 d.k. If it would not be ignored,
1951 // we would go cyclically to PreOp1 and on next
1952 // SoC back to PreOp2.
1957 case kEplNmtEventDllCePreq:
1958 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
1959 DllEvent.m_ulDllErrorEvents |=
1960 EPL_DLL_ERR_CN_LOSS_SOA |
1961 EPL_DLL_ERR_CN_LOSS_SOC;
1963 case kEplNmtEventDllCeSoa:
1964 // enter DLL_CS_WAIT_SOC
1965 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1969 case kEplNmtEventDllCeSoc:
1970 // report DLL_CEV_LOSS_SOA
1971 DllEvent.m_ulDllErrorEvents |=
1972 EPL_DLL_ERR_CN_LOSS_SOA;
1974 // enter DLL_CS_WAIT_PREQ
1975 EplDllkInstance_g.m_DllState =
1980 case kEplNmtEventDllCeAsnd:
1981 // report DLL_CEV_LOSS_SOA
1982 DllEvent.m_ulDllErrorEvents |=
1983 EPL_DLL_ERR_CN_LOSS_SOA;
1985 case kEplNmtEventDllCePres:
1987 // remain in this state
1993 // enter DLL_CS_WAIT_PREQ
1994 EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
2002 case kEplNmtCsStopped:
2003 // full EPL cycle is active, but without PReq/PRes
2005 switch (EplDllkInstance_g.m_DllState) {
2006 case kEplDllCsWaitPreq:
2007 switch (NmtEvent_p) {
2009 case kEplNmtEventDllCePreq:
2010 // enter DLL_CS_WAIT_SOA
2011 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2015 case kEplNmtEventDllCeFrameTimeout:
2016 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
2017 DllEvent.m_ulDllErrorEvents |=
2018 EPL_DLL_ERR_CN_LOSS_SOA |
2019 EPL_DLL_ERR_CN_LOSS_SOC;
2021 case kEplNmtEventDllCeSoa:
2022 // NMT_CS_STOPPED active
2023 // it is Ok if no PReq was received
2025 // enter DLL_CS_WAIT_SOC
2026 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2030 case kEplNmtEventDllCeSoc:
2031 case kEplNmtEventDllCeAsnd:
2032 // report DLL_CEV_LOSS_SOA
2033 DllEvent.m_ulDllErrorEvents |=
2034 EPL_DLL_ERR_CN_LOSS_SOA;
2036 case kEplNmtEventDllCePres:
2038 // remain in this state
2043 case kEplDllCsWaitSoc:
2044 switch (NmtEvent_p) {
2046 case kEplNmtEventDllCeSoc:
2047 // start of cycle and isochronous phase
2048 // enter DLL_CS_WAIT_SOA
2049 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2053 // case kEplNmtEventDllCePres:
2054 case kEplNmtEventDllCePreq:
2055 case kEplNmtEventDllCeSoa:
2056 case kEplNmtEventDllCeFrameTimeout:
2057 // report DLL_CEV_LOSS_SOC
2058 DllEvent.m_ulDllErrorEvents |=
2059 EPL_DLL_ERR_CN_LOSS_SOC;
2061 case kEplNmtEventDllCeAsnd:
2063 // remain in this state
2068 case kEplDllCsWaitSoa:
2069 switch (NmtEvent_p) {
2071 case kEplNmtEventDllCeFrameTimeout:
2072 // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
2073 DllEvent.m_ulDllErrorEvents |=
2074 EPL_DLL_ERR_CN_LOSS_SOA |
2075 EPL_DLL_ERR_CN_LOSS_SOC;
2077 case kEplNmtEventDllCeSoa:
2078 // enter DLL_CS_WAIT_SOC
2079 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2083 case kEplNmtEventDllCeSoc:
2084 // report DLL_CEV_LOSS_SOA
2085 DllEvent.m_ulDllErrorEvents |=
2086 EPL_DLL_ERR_CN_LOSS_SOA;
2087 // remain in DLL_CS_WAIT_SOA
2091 case kEplNmtEventDllCeAsnd:
2092 // report DLL_CEV_LOSS_SOA
2093 DllEvent.m_ulDllErrorEvents |=
2094 EPL_DLL_ERR_CN_LOSS_SOA;
2096 case kEplNmtEventDllCePreq:
2097 // NMT_CS_STOPPED active and we do not expect any PReq
2098 // so just ignore it
2099 case kEplNmtEventDllCePres:
2101 // remain in this state
2108 // enter DLL_CS_WAIT_PREQ
2109 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2114 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2115 case kEplNmtMsNotActive:
2116 case kEplNmtMsBasicEthernet:
2119 case kEplNmtMsPreOperational1:
2120 // reduced EPL cycle is active
2121 if (EplDllkInstance_g.m_DllState != kEplDllMsNonCyclic) { // stop cycle timer
2122 #if EPL_TIMER_USE_HIGHRES != FALSE
2124 EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
2127 EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
2129 // stop further processing,
2130 // because it will be restarted by NMT MN module
2134 switch (NmtEvent_p) {
2135 case kEplNmtEventDllMeSocTrig:
2136 case kEplNmtEventDllCeAsnd:
2137 { // because of reduced EPL cycle SoA shall be triggered, not SoC
2138 tEplDllState DummyDllState;
2141 EplDllkAsyncFrameNotReceived
2142 (EplDllkInstance_g.m_LastReqServiceId,
2143 EplDllkInstance_g.m_uiLastTargetNodeId);
2145 // go ahead and send SoA
2146 Ret = EplDllkMnSendSoa(NmtState_p,
2150 EPL_C_DLL_PREOP1_START_CYCLES));
2151 // increment cycle counter to detect if EPL_C_DLL_PREOP1_START_CYCLES empty cycles are elapsed
2152 EplDllkInstance_g.m_uiCycleCount++;
2155 #if EPL_TIMER_USE_HIGHRES != FALSE
2156 if (EplDllkInstance_g.m_DllConfigParam.
2157 m_dwAsyncSlotTimeout != 0) {
2159 EplTimerHighReskModifyTimerNs
2160 (&EplDllkInstance_g.m_TimerHdlCycle,
2161 EplDllkInstance_g.m_DllConfigParam.
2162 m_dwAsyncSlotTimeout,
2163 EplDllkCbMnTimerCycle, 0L, FALSE);
2174 case kEplNmtMsPreOperational2:
2175 case kEplNmtMsReadyToOperate:
2176 case kEplNmtMsOperational:
2177 // full EPL cycle is active
2178 switch (NmtEvent_p) {
2179 case kEplNmtEventDllMeSocTrig:
2181 // update cycle counter
2182 if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) { // multiplexed cycle active
2183 EplDllkInstance_g.m_uiCycleCount =
2184 (EplDllkInstance_g.m_uiCycleCount +
2186 EplDllkInstance_g.m_DllConfigParam.
2187 m_uiMultiplCycleCnt;
2188 // $$$ check multiplexed cycle restart
2189 // -> toggle MC flag
2190 // -> change node linked list
2191 } else { // non-multiplexed cycle active
2192 // start with first node in isochronous phase
2193 EplDllkInstance_g.m_pCurNodeInfo = NULL;
2196 switch (EplDllkInstance_g.m_DllState) {
2197 case kEplDllMsNonCyclic:
2198 { // start continuous cycle timer
2199 #if EPL_TIMER_USE_HIGHRES != FALSE
2201 EplTimerHighReskModifyTimerNs
2202 (&EplDllkInstance_g.
2206 EplDllkCbMnTimerCycle, 0L,
2209 // continue with sending SoC
2212 case kEplDllMsWaitAsnd:
2213 case kEplDllMsWaitSocTrig:
2214 { // if m_LastReqServiceId is still valid,
2215 // SoA was not correctly answered
2216 // and user part has to be informed
2218 EplDllkAsyncFrameNotReceived
2222 m_uiLastTargetNodeId);
2225 Ret = EplDllkMnSendSoc();
2228 EplDllkInstance_g.m_DllState =
2229 kEplDllMsWaitPreqTrig;
2231 // start WaitSoCPReq Timer
2232 #if EPL_TIMER_USE_HIGHRES != FALSE
2234 EplTimerHighReskModifyTimerNs
2235 (&EplDllkInstance_g.
2240 EplDllkCbMnTimerResponse,
2247 { // wrong DLL state / cycle time exceeded
2248 DllEvent.m_ulDllErrorEvents |=
2249 EPL_DLL_ERR_MN_CYCTIMEEXCEED;
2250 EplDllkInstance_g.m_DllState =
2251 kEplDllMsWaitSocTrig;
2259 case kEplNmtEventDllMePresTimeout:
2262 switch (EplDllkInstance_g.m_DllState) {
2263 case kEplDllMsWaitPres:
2264 { // PRes not received
2266 if (EplDllkInstance_g.m_pCurNodeInfo->m_fSoftDelete == FALSE) { // normal isochronous CN
2270 EPL_DLL_ERR_MN_CN_LOSS_PRES;
2271 DllEvent.m_uiNodeId =
2275 } else { // CN shall be deleted softly
2277 kEplEventSinkDllkCal;
2279 kEplEventTypeDllkSoftDelNode;
2280 // $$$ d.k. set Event.m_NetTime to current time
2293 // continue with sending next PReq
2296 case kEplDllMsWaitPreqTrig:
2309 { // wrong DLL state
2317 case kEplNmtEventDllCePres:
2320 switch (EplDllkInstance_g.m_DllState) {
2321 case kEplDllMsWaitPres:
2334 { // wrong DLL state
2342 case kEplNmtEventDllMeSoaTrig:
2345 switch (EplDllkInstance_g.m_DllState) {
2346 case kEplDllMsWaitSoaTrig:
2350 EplDllkMnSendSoa(NmtState_p,
2359 { // wrong DLL state
2367 case kEplNmtEventDllCeAsnd:
2368 { // ASnd has been received, but it may be not the requested one
2370 // report if SoA was correctly answered
2371 Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId,
2372 EplDllkInstance_g.m_uiLastTargetNodeId);
2374 if (EplDllkInstance_g.m_DllState ==
2375 kEplDllMsWaitAsnd) {
2376 EplDllkInstance_g.m_DllState =
2377 kEplDllMsWaitSocTrig;
2386 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2392 if (DllEvent.m_ulDllErrorEvents != 0) { // error event set -> post it to error handler
2393 Event.m_EventSink = kEplEventSinkErrk;
2394 Event.m_EventType = kEplEventTypeDllError;
2395 // $$$ d.k. set Event.m_NetTime to current time
2396 Event.m_uiSize = sizeof(DllEvent);
2397 Event.m_pArg = &DllEvent;
2398 Ret = EplEventkPost(&Event);
2404 //---------------------------------------------------------------------------
2406 // Function: EplDllkCbFrameReceived()
2408 // Description: called from EdrvInterruptHandler()
2410 // Parameters: pRxBuffer_p = receive buffer structure
2417 //---------------------------------------------------------------------------
2419 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p)
2421 tEplKernel Ret = kEplSuccessful;
2422 tEplNmtState NmtState;
2423 tEplNmtEvent NmtEvent = kEplNmtEventNoEvent;
2426 tEplFrame *pTxFrame;
2427 tEdrvTxBuffer *pTxBuffer = NULL;
2428 tEplFrameInfo FrameInfo;
2429 tEplMsgType MsgType;
2430 tEplDllReqServiceId ReqServiceId;
2431 unsigned int uiAsndServiceId;
2432 unsigned int uiNodeId;
2435 BENCHMARK_MOD_02_SET(3);
2436 NmtState = EplNmtkGetNmtState();
2438 if (NmtState <= kEplNmtGsResetConfiguration) {
2442 pFrame = (tEplFrame *) pRxBuffer_p->m_pbBuffer;
2444 #if EDRV_EARLY_RX_INT != FALSE
2445 switch (pRxBuffer_p->m_BufferInFrame) {
2446 case kEdrvBufferFirstInFrame:
2449 (tEplMsgType) AmiGetByteFromLe(&pFrame->
2451 if (MsgType == kEplMsgTypePreq) {
2452 if (EplDllkInstance_g.m_DllState == kEplDllCsWaitPreq) { // PReq expected and actually received
2453 // d.k.: The condition above is sufficent, because EPL cycle is active
2454 // and no non-EPL frame shall be received in isochronous phase.
2455 // start transmission PRes
2456 // $$$ What if Tx buffer is invalid?
2459 m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
2460 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2461 Ret = EdrvTxMsgStart(pTxBuffer);
2464 (tEplFrame *) pTxBuffer->m_pbBuffer;
2465 // update frame (NMT state, RD, RS, PR, MS, EN flags)
2466 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2469 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2473 if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
2474 // $$$ reset only RD flag; set other flags appropriately
2475 AmiSetByteToLe(&pTxFrame->
2479 // $$$ make function that updates Pres, StatusRes
2481 Ret = EdrvSendTxMsg(pTxBuffer);
2488 case kEdrvBufferMiddleInFrame:
2493 case kEdrvBufferLastInFrame:
2500 FrameInfo.m_pFrame = pFrame;
2501 FrameInfo.m_uiFrameSize = pRxBuffer_p->m_uiRxMsgLen;
2502 FrameInfo.m_NetTime.m_dwNanoSec = pRxBuffer_p->m_NetTime.m_dwNanoSec;
2503 FrameInfo.m_NetTime.m_dwSec = pRxBuffer_p->m_NetTime.m_dwSec;
2505 if (AmiGetWordFromBe(&pFrame->m_be_wEtherType) != EPL_C_DLL_ETHERTYPE_EPL) { // non-EPL frame
2506 //TRACE2("EplDllkCbFrameReceived: pfnCbAsync=0x%p SrcMAC=0x%llx\n", EplDllkInstance_g.m_pfnCbAsync, AmiGetQword48FromBe(pFrame->m_be_abSrcMac));
2507 if (EplDllkInstance_g.m_pfnCbAsync != NULL) { // handler for async frames is registered
2508 EplDllkInstance_g.m_pfnCbAsync(&FrameInfo);
2514 MsgType = (tEplMsgType) AmiGetByteFromLe(&pFrame->m_le_bMessageType);
2516 case kEplMsgTypePreq:
2519 // d.k.: (we assume that this PReq frame is intended for us and don't check DstNodeId)
2520 if (AmiGetByteFromLe(&pFrame->m_le_bDstNodeId) != EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) { // this PReq is not intended for us
2523 NmtEvent = kEplNmtEventDllCePreq;
2525 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2528 #if EDRV_EARLY_RX_INT == FALSE
2529 if (NmtState >= kEplNmtCsPreOperational2) { // respond to and process PReq frames only in PreOp2, ReadyToOp and Op
2533 m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
2534 if (pTxBuffer->m_pbBuffer != NULL) { // PRes does exist
2535 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2536 EdrvTxMsgStart(pTxBuffer);
2539 (tEplFrame *) pTxBuffer->m_pbBuffer;
2540 // update frame (NMT state, RD, RS, PR, MS, EN flags)
2541 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2544 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2549 AmiGetByteFromLe(&pFrame->m_Data.
2553 EplDllkInstance_g.m_bMnFlag1 =
2555 m_bMnFlag1 & ~EPL_FRAME_FLAG1_EA)
2556 | (bFlag1 & EPL_FRAME_FLAG1_EA);
2558 bFlag1 &= EPL_FRAME_FLAG1_MS;
2559 // add EN flag from Error signaling module
2562 m_bFlag1 & EPL_FRAME_FLAG1_EN;
2563 if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
2564 // reset only RD flag
2565 AmiSetByteToLe(&pTxFrame->
2569 } else { // leave RD flag untouched
2570 AmiSetByteToLe(&pTxFrame->
2580 // $$$ update EPL_DLL_PRES_READY_AFTER_* code
2582 Ret = EdrvSendTxMsg(pTxBuffer);
2583 if (Ret != kEplSuccessful) {
2589 // inform PDO module
2590 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2591 if (NmtState >= kEplNmtCsReadyToOperate) { // inform PDO module only in ReadyToOp and Op
2592 if (NmtState != kEplNmtCsOperational) {
2593 // reset RD flag and all other flags, but that does not matter, because they were processed above
2594 AmiSetByteToLe(&pFrame->m_Data.
2598 // compares real frame size and PDO size
2600 int)(AmiGetWordFromLe(&pFrame->
2605 > FrameInfo.m_uiFrameSize) { // format error
2606 tEplErrorHandlerkEvent DllEvent;
2608 DllEvent.m_ulDllErrorEvents =
2609 EPL_DLL_ERR_INVALID_FORMAT;
2610 DllEvent.m_uiNodeId =
2611 AmiGetByteFromLe(&pFrame->
2613 DllEvent.m_NmtState = NmtState;
2617 kEplEventTypeDllError;
2619 FrameInfo.m_NetTime;
2622 Event.m_pArg = &DllEvent;
2623 Ret = EplEventkPost(&Event);
2626 // forward PReq frame as RPDO to PDO module
2627 Ret = EplPdokCbPdoReceived(&FrameInfo);
2630 #if (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2631 if (pTxBuffer->m_pbBuffer != NULL) { // PRes does exist
2632 // inform PDO module about PRes after PReq
2633 FrameInfo.m_pFrame =
2634 (tEplFrame *) pTxBuffer->m_pbBuffer;
2635 FrameInfo.m_uiFrameSize =
2636 pTxBuffer->m_uiMaxBufferLen;
2638 EplPdokCbPdoTransmitted(&FrameInfo);
2643 #if EDRV_EARLY_RX_INT == FALSE
2644 // $$$ inform emergency protocol handling (error signaling module) about flags
2648 // reset cycle counter
2649 EplDllkInstance_g.m_uiCycleCount = 0;
2654 case kEplMsgTypePres:
2656 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2657 tEplDllkNodeInfo *pIntNodeInfo;
2658 tEplHeartbeatEvent HeartbeatEvent;
2662 NmtEvent = kEplNmtEventDllCePres;
2664 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
2666 if ((NmtState >= kEplNmtCsPreOperational2)
2667 && (NmtState <= kEplNmtCsOperational)) { // process PRes frames only in PreOp2, ReadyToOp and Op of CN
2669 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2670 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId);
2671 if (pIntNodeInfo == NULL) { // no node info structure available
2672 Ret = kEplDllNoNodeInfo;
2675 } else if (EplDllkInstance_g.m_DllState == kEplDllMsWaitPres) { // or process PRes frames in MsWaitPres
2677 pIntNodeInfo = EplDllkInstance_g.m_pCurNodeInfo;
2678 if ((pIntNodeInfo == NULL) || (pIntNodeInfo->m_uiNodeId != uiNodeId)) { // ignore PRes, because it is from wrong CN
2679 // $$$ maybe post event to NmtMn module
2682 // forward Flag2 to asynchronous scheduler
2684 AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.
2685 m_Payload.m_StatusResponse.
2688 EplDllkCalAsyncSetPendingRequests(uiNodeId,
2689 ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), (bFlag1 & EPL_FRAME_FLAG2_RS));
2692 } else { // ignore PRes, because it was received in wrong NMT state
2693 // but execute EplDllkChangeState() and post event to NMT module
2697 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2698 { // check NMT state of CN
2699 HeartbeatEvent.m_wErrorCode = EPL_E_NO_ERROR;
2700 HeartbeatEvent.m_NmtState =
2701 (tEplNmtState) (AmiGetByteFromLe
2702 (&pFrame->m_Data.m_Pres.
2705 if (pIntNodeInfo->m_NmtState != HeartbeatEvent.m_NmtState) { // NMT state of CN has changed -> post event to NmtMnu module
2706 if (pIntNodeInfo->m_fSoftDelete == FALSE) { // normal isochronous CN
2707 HeartbeatEvent.m_uiNodeId =
2710 kEplEventSinkNmtMnu;
2712 kEplEventTypeHeartbeat;
2714 sizeof(HeartbeatEvent);
2715 Event.m_pArg = &HeartbeatEvent;
2716 } else { // CN shall be deleted softly
2718 kEplEventSinkDllkCal;
2720 kEplEventTypeDllkSoftDelNode;
2722 sizeof(unsigned int);
2724 &pIntNodeInfo->m_uiNodeId;
2726 Event.m_NetTime = FrameInfo.m_NetTime;
2727 Ret = EplEventkPost(&Event);
2729 // save current NMT state of CN in internal node structure
2730 pIntNodeInfo->m_NmtState =
2731 HeartbeatEvent.m_NmtState;
2736 // inform PDO module
2737 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2738 if ((NmtState != kEplNmtCsPreOperational2)
2739 && (NmtState != kEplNmtMsPreOperational2)) { // inform PDO module only in ReadyToOp and Op
2740 // compare real frame size and PDO size?
2742 int)(AmiGetWordFromLe(&pFrame->m_Data.
2743 m_Pres.m_le_wSize) +
2745 > FrameInfo.m_uiFrameSize)
2746 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2749 (&pFrame->m_Data.m_Pres.m_le_wSize) >
2750 pIntNodeInfo->m_wPresPayloadLimit)
2753 tEplErrorHandlerkEvent DllEvent;
2755 DllEvent.m_ulDllErrorEvents =
2756 EPL_DLL_ERR_INVALID_FORMAT;
2757 DllEvent.m_uiNodeId = uiNodeId;
2758 DllEvent.m_NmtState = NmtState;
2759 Event.m_EventSink = kEplEventSinkErrk;
2761 kEplEventTypeDllError;
2762 Event.m_NetTime = FrameInfo.m_NetTime;
2763 Event.m_uiSize = sizeof(DllEvent);
2764 Event.m_pArg = &DllEvent;
2765 Ret = EplEventkPost(&Event);
2768 if ((NmtState != kEplNmtCsOperational)
2769 && (NmtState != kEplNmtMsOperational)) {
2770 // reset RD flag and all other flags, but that does not matter, because they were processed above
2771 AmiSetByteToLe(&pFrame->m_Data.m_Pres.
2774 Ret = EplPdokCbPdoReceived(&FrameInfo);
2781 case kEplMsgTypeSoc:
2784 NmtEvent = kEplNmtEventDllCeSoc;
2786 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2789 #if EPL_DLL_PRES_READY_AFTER_SOC != FALSE
2790 // post PRes to transmit FIFO of the ethernet controller, but don't start
2791 // transmission over bus
2794 m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
2796 if (pTxBuffer->m_pbBuffer != NULL) { // PRes does exist
2797 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
2798 // update frame (NMT state, RD, RS, PR, MS, EN flags)
2799 if (NmtState < kEplNmtCsPreOperational2) { // NMT state is not PreOp2, ReadyToOp or Op
2800 // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
2801 NmtState = kEplNmtCsPreOperational2;
2803 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2806 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2808 EplDllkInstance_g.m_bFlag2);
2809 if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
2810 // $$$ reset only RD flag; set other flags appropriately
2811 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2814 // $$$ make function that updates Pres, StatusRes
2815 // mark PRes frame as ready for transmission
2816 Ret = EdrvTxMsgReady(pTxBuffer);
2820 if (NmtState >= kEplNmtCsPreOperational2) { // SoC frames only in PreOp2, ReadyToOp and Op
2821 // trigger synchronous task
2822 Event.m_EventSink = kEplEventSinkSync;
2823 Event.m_EventType = kEplEventTypeSync;
2825 Ret = EplEventkPost(&Event);
2827 // update cycle counter
2828 if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) { // multiplexed cycle active
2829 EplDllkInstance_g.m_uiCycleCount =
2830 (EplDllkInstance_g.m_uiCycleCount +
2832 EplDllkInstance_g.m_DllConfigParam.
2833 m_uiMultiplCycleCnt;
2837 #if EPL_TIMER_USE_HIGHRES != FALSE
2838 if (EplDllkInstance_g.m_ullFrameTimeout != 0) {
2840 EplTimerHighReskModifyTimerNs
2841 (&EplDllkInstance_g.m_TimerHdlCycle,
2842 EplDllkInstance_g.m_ullFrameTimeout,
2843 EplDllkCbCnTimer, 0L, FALSE);
2850 case kEplMsgTypeSoa:
2853 NmtEvent = kEplNmtEventDllCeSoa;
2855 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2861 if ((NmtState & EPL_NMT_SUPERSTATE_MASK) != EPL_NMT_CS_EPLMODE) { // do not respond, if NMT state is < PreOp1 (i.e. not EPL_MODE)
2864 // check TargetNodeId
2866 AmiGetByteFromLe(&pFrame->m_Data.m_Soa.
2867 m_le_bReqServiceTarget);
2868 if (uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) { // local node is the target of the current request
2872 (tEplDllReqServiceId)
2873 AmiGetByteFromLe(&pFrame->m_Data.m_Soa.
2874 m_le_bReqServiceId);
2875 if (ReqServiceId == kEplDllReqServiceStatus) { // StatusRequest
2876 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) { // StatusRes does exist
2882 [EPL_DLLK_TXFRAME_STATUSRES].
2884 // update StatusRes frame (NMT state, EN, EC, RS, PR flags)
2885 AmiSetByteToLe(&pTxFrame->
2891 AmiSetByteToLe(&pTxFrame->
2898 AmiSetByteToLe(&pTxFrame->
2908 (&EplDllkInstance_g.
2910 [EPL_DLLK_TXFRAME_STATUSRES]);
2911 if (Ret != kEplSuccessful) {
2914 TGT_DBG_SIGNAL_TRACE_POINT(8);
2916 // update error signaling
2918 AmiGetByteFromLe(&pFrame->
2922 if (((bFlag1 ^ EplDllkInstance_g.m_bMnFlag1) & EPL_FRAME_FLAG1_ER) != 0) { // exception reset flag was changed by MN
2923 // assume same state for EC in next cycle (clear all other bits)
2927 // set EC and reset rest
2932 // reset complete flag 1 (including EC and EN)
2938 // save flag 1 from MN for Status request response cycle
2939 EplDllkInstance_g.m_bMnFlag1 =
2942 } else if (ReqServiceId == kEplDllReqServiceIdent) { // IdentRequest
2943 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) { // IdentRes does exist
2948 [EPL_DLLK_TXFRAME_IDENTRES].
2950 // update IdentRes frame (NMT state, RS, PR flags)
2951 AmiSetByteToLe(&pTxFrame->
2957 AmiSetByteToLe(&pTxFrame->
2967 (&EplDllkInstance_g.
2969 [EPL_DLLK_TXFRAME_IDENTRES]);
2970 if (Ret != kEplSuccessful) {
2973 TGT_DBG_SIGNAL_TRACE_POINT(7);
2975 } else if (ReqServiceId == kEplDllReqServiceNmtRequest) { // NmtRequest
2976 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) { // NmtRequest does exist
2977 // check if frame is not empty and not being filled
2978 if (EplDllkInstance_g.
2980 [EPL_DLLK_TXFRAME_NMTREQ].
2982 EPL_DLLK_BUFLEN_FILLING) {
2983 /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
2985 EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
2987 // memorize transmission
2993 (&EplDllkInstance_g.
2995 [EPL_DLLK_TXFRAME_NMTREQ]);
3004 } else if (ReqServiceId == kEplDllReqServiceUnspecified) { // unspecified invite
3005 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) { // non-EPL frame does exist
3006 // check if frame is not empty and not being filled
3007 if (EplDllkInstance_g.
3009 [EPL_DLLK_TXFRAME_NONEPL].
3011 EPL_DLLK_BUFLEN_FILLING) {
3012 /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
3014 EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
3016 // memorize transmission
3019 // send non-EPL frame
3022 (&EplDllkInstance_g.
3024 [EPL_DLLK_TXFRAME_NONEPL]);
3033 } else if (ReqServiceId == kEplDllReqServiceNo) { // no async service requested -> do nothing
3036 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3037 if (pTxFrame == NULL) { // signal process function readiness of PRes frame
3038 Event.m_EventSink = kEplEventSinkDllk;
3039 Event.m_EventType = kEplEventTypeDllkPresReady;
3041 Event.m_pArg = NULL;
3042 Ret = EplEventkPost(&Event);
3046 // inform PDO module
3047 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
3048 // Ret = EplPdokCbSoa(&FrameInfo);
3051 // $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
3053 // $$$ inform emergency protocol handling about flags
3057 case kEplMsgTypeAsnd:
3060 NmtEvent = kEplNmtEventDllCeAsnd;
3062 // ASnd service registered?
3064 (unsigned int)AmiGetByteFromLe(&pFrame->m_Data.
3068 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3069 if ((EplDllkInstance_g.m_DllState >= kEplDllMsNonCyclic)
3071 ((((tEplDllAsndServiceId) uiAsndServiceId) ==
3072 kEplDllAsndStatusResponse)
3073 || (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse))) { // StatusRes or IdentRes received
3075 AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
3076 if ((EplDllkInstance_g.m_LastReqServiceId ==
3077 ((tEplDllReqServiceId) uiAsndServiceId))
3078 && (uiNodeId == EplDllkInstance_g.m_uiLastTargetNodeId)) { // mark request as responded
3079 EplDllkInstance_g.m_LastReqServiceId =
3080 kEplDllReqServiceNo;
3082 if (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse) { // memorize MAC address of CN for PReq
3083 tEplDllkNodeInfo *pIntNodeInfo;
3086 EplDllkGetNodeInfo(uiNodeId);
3087 if (pIntNodeInfo == NULL) { // no node info structure available
3088 Ret = kEplDllNoNodeInfo;
3090 EPL_MEMCPY(pIntNodeInfo->
3096 // forward Flag2 to asynchronous scheduler
3098 AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.
3099 m_Payload.m_StatusResponse.
3102 EplDllkCalAsyncSetPendingRequests(uiNodeId,
3103 ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), (bFlag1 & EPL_FRAME_FLAG2_RS));
3107 if (uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID) { // ASnd service ID is valid
3108 if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterAny) { // ASnd service ID is registered
3109 // forward frame via async receive FIFO to userspace
3111 EplDllkCalAsyncFrameReceived
3113 } else if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterLocal) { // ASnd service ID is registered, but only local node ID or broadcasts
3114 // shall be forwarded
3116 AmiGetByteFromLe(&pFrame->
3119 EplDllkInstance_g.m_DllConfigParam.
3121 || (uiNodeId == EPL_C_ADR_BROADCAST)) { // ASnd frame is intended for us
3122 // forward frame via async receive FIFO to userspace
3124 EplDllkCalAsyncFrameReceived
3138 if (NmtEvent != kEplNmtEventNoEvent) { // event for DLL and NMT state machine generated
3139 Ret = EplDllkChangeState(NmtEvent, NmtState);
3140 if (Ret != kEplSuccessful) {
3144 if ((NmtEvent != kEplNmtEventDllCeAsnd)
3145 && ((NmtState <= kEplNmtCsPreOperational1) || (NmtEvent != kEplNmtEventDllCePres))) { // NMT state machine is not interested in ASnd frames and PRes frames when not CsNotActive or CsPreOp1
3146 // inform NMT module
3147 Event.m_EventSink = kEplEventSinkNmtk;
3148 Event.m_EventType = kEplEventTypeNmtEvent;
3149 Event.m_uiSize = sizeof(NmtEvent);
3150 Event.m_pArg = &NmtEvent;
3151 Ret = EplEventkPost(&Event);
3156 if (Ret != kEplSuccessful) {
3159 BENCHMARK_MOD_02_TOGGLE(9);
3161 dwArg = EplDllkInstance_g.m_DllState | (NmtEvent << 8);
3163 // Error event for API layer
3164 Ret = EplEventkPostError(kEplEventSourceDllk,
3165 Ret, sizeof(dwArg), &dwArg);
3167 BENCHMARK_MOD_02_RESET(3);
3171 //---------------------------------------------------------------------------
3173 // Function: EplDllkCbFrameTransmitted()
3175 // Description: called from EdrvInterruptHandler().
3178 // Parameters: pRxBuffer_p = receive buffer structure
3185 //---------------------------------------------------------------------------
3187 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p)
3189 tEplKernel Ret = kEplSuccessful;
3191 tEplDllAsyncReqPriority Priority;
3192 tEplNmtState NmtState;
3194 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3195 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)
3196 tEplFrameInfo FrameInfo;
3199 NmtState = EplNmtkGetNmtState();
3201 if (NmtState <= kEplNmtGsResetConfiguration) {
3205 if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NMTREQ) { // frame from NMT request FIFO sent
3206 // mark Tx-buffer as empty
3207 pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
3209 // post event to DLL
3210 Priority = kEplDllAsyncReqPrioNmt;
3211 Event.m_EventSink = kEplEventSinkDllk;
3212 Event.m_EventType = kEplEventTypeDllkFillTx;
3213 EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
3214 Event.m_pArg = &Priority;
3215 Event.m_uiSize = sizeof(Priority);
3216 Ret = EplEventkPost(&Event);
3217 } else if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NONEPL) { // frame from generic priority FIFO sent
3218 // mark Tx-buffer as empty
3219 pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
3221 // post event to DLL
3222 Priority = kEplDllAsyncReqPrioGeneric;
3223 Event.m_EventSink = kEplEventSinkDllk;
3224 Event.m_EventType = kEplEventTypeDllkFillTx;
3225 EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
3226 Event.m_pArg = &Priority;
3227 Event.m_uiSize = sizeof(Priority);
3228 Ret = EplEventkPost(&Event);
3230 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3231 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)) \
3232 || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3233 else if ((pTxBuffer_p->m_EplMsgType == kEplMsgTypePreq)
3234 || (pTxBuffer_p->m_EplMsgType == kEplMsgTypePres)) { // PRes resp. PReq frame sent
3236 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3237 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE))
3239 // inform PDO module
3240 FrameInfo.m_pFrame =
3241 (tEplFrame *) pTxBuffer_p->m_pbBuffer;
3242 FrameInfo.m_uiFrameSize = pTxBuffer_p->m_uiMaxBufferLen;
3243 Ret = EplPdokCbPdoTransmitted(&FrameInfo);
3247 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3249 // if own Pres on MN, trigger SoA
3250 if ((NmtState >= kEplNmtMsPreOperational2)
3253 m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) {
3255 EplDllkChangeState(kEplNmtEventDllMeSoaTrig,
3261 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3266 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3267 else if (pTxBuffer_p->m_EplMsgType == kEplMsgTypeSoa) { // SoA frame sent
3268 tEplNmtEvent NmtEvent = kEplNmtEventDllMeSoaSent;
3270 // check if we are invited
3271 if (EplDllkInstance_g.m_uiLastTargetNodeId ==
3272 EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {
3273 tEplFrame *pTxFrame;
3275 if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceStatus) { // StatusRequest
3276 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) { // StatusRes does exist
3279 (tEplFrame *) EplDllkInstance_g.
3281 [EPL_DLLK_TXFRAME_STATUSRES].
3283 // update StatusRes frame (NMT state, EN, EC, RS, PR flags)
3284 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3289 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3295 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3303 EdrvSendTxMsg(&EplDllkInstance_g.
3305 [EPL_DLLK_TXFRAME_STATUSRES]);
3306 if (Ret != kEplSuccessful) {
3309 TGT_DBG_SIGNAL_TRACE_POINT(8);
3312 } else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceIdent) { // IdentRequest
3313 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) { // IdentRes does exist
3315 (tEplFrame *) EplDllkInstance_g.
3317 [EPL_DLLK_TXFRAME_IDENTRES].
3319 // update IdentRes frame (NMT state, RS, PR flags)
3320 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3325 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3333 EdrvSendTxMsg(&EplDllkInstance_g.
3335 [EPL_DLLK_TXFRAME_IDENTRES]);
3336 if (Ret != kEplSuccessful) {
3339 TGT_DBG_SIGNAL_TRACE_POINT(7);
3341 } else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceNmtRequest) { // NmtRequest
3342 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) { // NmtRequest does exist
3343 // check if frame is not empty and not being filled
3344 if (EplDllkInstance_g.
3346 [EPL_DLLK_TXFRAME_NMTREQ].
3348 EPL_DLLK_BUFLEN_FILLING) {
3349 // check if this frame is a NMT command,
3350 // then forward this frame back to NmtMnu module,
3351 // because it needs the time, when this frame is
3352 // actually sent, to start the timer for monitoring
3353 // the NMT state change.
3359 [EPL_DLLK_TXFRAME_NMTREQ].
3361 if ((AmiGetByteFromLe
3364 == (u8) kEplMsgTypeAsnd)
3367 (&pTxFrame->m_Data.m_Asnd.
3369 == (u8) kEplDllAsndNmtCommand)) { // post event directly to NmtMnu module
3371 kEplEventSinkNmtMnu;
3373 kEplEventTypeNmtMnuNmtCmdSent;
3377 [EPL_DLLK_TXFRAME_NMTREQ].
3379 Event.m_pArg = pTxFrame;
3388 (&EplDllkInstance_g.
3390 [EPL_DLLK_TXFRAME_NMTREQ]);
3391 if (Ret != kEplSuccessful) {
3398 } else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceUnspecified) { // unspecified invite
3399 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) { // non-EPL frame does exist
3400 // check if frame is not empty and not being filled
3401 if (EplDllkInstance_g.
3403 [EPL_DLLK_TXFRAME_NONEPL].
3405 EPL_DLLK_BUFLEN_FILLING) {
3406 // send non-EPL frame
3409 (&EplDllkInstance_g.
3411 [EPL_DLLK_TXFRAME_NONEPL]);
3412 if (Ret != kEplSuccessful) {
3419 // ASnd frame was sent, remove the request
3420 EplDllkInstance_g.m_LastReqServiceId =
3421 kEplDllReqServiceNo;
3423 // forward event to ErrorHandler and PDO module
3424 Event.m_EventSink = kEplEventSinkNmtk;
3425 Event.m_EventType = kEplEventTypeNmtEvent;
3426 Event.m_uiSize = sizeof(NmtEvent);
3427 Event.m_pArg = &NmtEvent;
3428 Ret = EplEventkPost(&Event);
3429 if (Ret != kEplSuccessful) {
3435 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3436 else { // d.k.: Why that else? on CN it is entered on IdentRes and StatusRes
3440 // signal process function readiness of PRes frame
3441 Event.m_EventSink = kEplEventSinkDllk;
3442 Event.m_EventType = kEplEventTypeDllkPresReady;
3444 Event.m_pArg = NULL;
3445 Ret = EplEventkPost(&Event);
3450 if (Ret != kEplSuccessful) {
3453 BENCHMARK_MOD_02_TOGGLE(9);
3456 EplDllkInstance_g.m_DllState | (pTxBuffer_p->
3457 m_EplMsgType << 16);
3459 // Error event for API layer
3460 Ret = EplEventkPostError(kEplEventSourceDllk,
3461 Ret, sizeof(dwArg), &dwArg);
3467 //---------------------------------------------------------------------------
3469 // Function: EplDllkCheckFrame()
3471 // Description: check frame and set missing information
3473 // Parameters: pFrame_p = ethernet frame
3474 // uiFrameSize_p = size of frame
3476 // Returns: tEplKernel = error code
3481 //---------------------------------------------------------------------------
3483 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
3484 unsigned int uiFrameSize_p)
3486 tEplMsgType MsgType;
3490 if (pFrame_p != NULL) {
3492 if (AmiGetQword48FromBe(pFrame_p->m_be_abSrcMac) == 0) {
3493 // source MAC address
3494 EPL_MEMCPY(&pFrame_p->m_be_abSrcMac[0],
3495 &EplDllkInstance_g.m_be_abSrcMac[0], 6);
3498 wEtherType = AmiGetWordFromBe(&pFrame_p->m_be_wEtherType);
3499 if (wEtherType == 0) {
3501 wEtherType = EPL_C_DLL_ETHERTYPE_EPL;
3502 AmiSetWordToBe(&pFrame_p->m_be_wEtherType, wEtherType);
3505 if (wEtherType == EPL_C_DLL_ETHERTYPE_EPL) {
3507 AmiSetByteToLe(&pFrame_p->m_le_bSrcNodeId,
3508 (u8) EplDllkInstance_g.
3509 m_DllConfigParam.m_uiNodeId);
3511 // check message type
3513 AmiGetByteFromLe(&pFrame_p->m_le_bMessageType);
3515 MsgType = kEplMsgTypeAsnd;
3516 AmiSetByteToLe(&pFrame_p->m_le_bMessageType,
3520 if (MsgType == kEplMsgTypeAsnd) {
3521 // destination MAC address
3522 AmiSetQword48ToBe(&pFrame_p->m_be_abDstMac[0],
3523 EPL_C_DLL_MULTICAST_ASND);
3529 return kEplSuccessful;
3532 //---------------------------------------------------------------------------
3534 // Function: EplDllkCbCnTimer()
3536 // Description: called by timer module. It monitors the EPL cycle when it is a CN.
3538 // Parameters: pEventArg_p = timer event argument
3540 // Returns: tEplKernel = error code
3545 //---------------------------------------------------------------------------
3547 #if EPL_TIMER_USE_HIGHRES != FALSE
3548 static tEplKernel EplDllkCbCnTimer(tEplTimerEventArg *pEventArg_p)
3550 tEplKernel Ret = kEplSuccessful;
3551 tEplNmtState NmtState;
3553 #if EPL_TIMER_USE_HIGHRES != FALSE
3554 if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) { // zombie callback
3560 NmtState = EplNmtkGetNmtState();
3562 if (NmtState <= kEplNmtGsResetConfiguration) {
3566 Ret = EplDllkChangeState(kEplNmtEventDllCeFrameTimeout, NmtState);
3567 if (Ret != kEplSuccessful) {
3570 // 2008/10/15 d.k. reprogramming of timer not necessary,
3571 // because it will be programmed, when SoC is received.
3574 #if EPL_TIMER_USE_HIGHRES != FALSE
3575 if ((NmtState > kEplNmtCsPreOperational1)
3576 && (EplDllkInstance_g.m_ullFrameTimeout != 0))
3578 Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE);
3584 if (Ret != kEplSuccessful) {
3587 BENCHMARK_MOD_02_TOGGLE(9);
3591 m_DllState | (kEplNmtEventDllCeFrameTimeout << 8);
3593 // Error event for API layer
3594 Ret = EplEventkPostError(kEplEventSourceDllk,
3595 Ret, sizeof(dwArg), &dwArg);
3602 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3604 //---------------------------------------------------------------------------
3606 // Function: EplDllkCbMnTimerCycle()
3608 // Description: called by timer module. It triggers the SoC when it is a MN.
3610 // Parameters: pEventArg_p = timer event argument
3612 // Returns: tEplKernel = error code
3617 //---------------------------------------------------------------------------
3619 static tEplKernel EplDllkCbMnTimerCycle(tEplTimerEventArg *pEventArg_p)
3621 tEplKernel Ret = kEplSuccessful;
3622 tEplNmtState NmtState;
3624 #if EPL_TIMER_USE_HIGHRES != FALSE
3625 if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) { // zombie callback
3631 NmtState = EplNmtkGetNmtState();
3633 if (NmtState <= kEplNmtGsResetConfiguration) {
3637 Ret = EplDllkChangeState(kEplNmtEventDllMeSocTrig, NmtState);
3640 if (Ret != kEplSuccessful) {
3643 BENCHMARK_MOD_02_TOGGLE(9);
3647 m_DllState | (kEplNmtEventDllMeSocTrig << 8);
3649 // Error event for API layer
3650 Ret = EplEventkPostError(kEplEventSourceDllk,
3651 Ret, sizeof(dwArg), &dwArg);
3657 //---------------------------------------------------------------------------
3659 // Function: EplDllkCbMnTimerResponse()
3661 // Description: called by timer module. It monitors the PRes timeout.
3663 // Parameters: pEventArg_p = timer event argument
3665 // Returns: tEplKernel = error code
3670 //---------------------------------------------------------------------------
3672 static tEplKernel EplDllkCbMnTimerResponse(tEplTimerEventArg *pEventArg_p)
3674 tEplKernel Ret = kEplSuccessful;
3675 tEplNmtState NmtState;
3677 #if EPL_TIMER_USE_HIGHRES != FALSE
3678 if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlResponse) { // zombie callback
3684 NmtState = EplNmtkGetNmtState();
3686 if (NmtState <= kEplNmtGsResetConfiguration) {
3690 Ret = EplDllkChangeState(kEplNmtEventDllMePresTimeout, NmtState);
3693 if (Ret != kEplSuccessful) {
3696 BENCHMARK_MOD_02_TOGGLE(9);
3700 m_DllState | (kEplNmtEventDllMePresTimeout << 8);
3702 // Error event for API layer
3703 Ret = EplEventkPostError(kEplEventSourceDllk,
3704 Ret, sizeof(dwArg), &dwArg);
3710 //---------------------------------------------------------------------------
3712 // Function: EplDllkGetNodeInfo()
3714 // Description: returns node info structure of the specified node.
3716 // Parameters: uiNodeId_p = node ID
3718 // Returns: tEplDllkNodeInfo* = pointer to internal node info structure
3723 //---------------------------------------------------------------------------
3725 static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p)
3727 // $$$ d.k.: use hash algorithm to retrieve the appropriate node info structure
3728 // if size of array is less than 254.
3729 uiNodeId_p--; // node ID starts at 1 but array at 0
3730 if (uiNodeId_p >= tabentries(EplDllkInstance_g.m_aNodeInfo)) {
3733 return &EplDllkInstance_g.m_aNodeInfo[uiNodeId_p];
3737 //---------------------------------------------------------------------------
3739 // Function: EplDllkMnSendSoa()
3741 // Description: it updates and transmits the SoA.
3743 // Parameters: NmtState_p = current NMT state
3744 // pDllStateProposed_p = proposed DLL state
3745 // fEnableInvitation_p = enable invitation for asynchronous phase
3746 // it will be disabled for EPL_C_DLL_PREOP1_START_CYCLES SoAs
3748 // Returns: tEplKernel = error code
3753 //---------------------------------------------------------------------------
3755 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
3756 tEplDllState * pDllStateProposed_p,
3757 BOOL fEnableInvitation_p)
3759 tEplKernel Ret = kEplSuccessful;
3760 tEdrvTxBuffer *pTxBuffer = NULL;
3761 tEplFrame *pTxFrame;
3762 tEplDllkNodeInfo *pNodeInfo;
3764 *pDllStateProposed_p = kEplDllMsNonCyclic;
3766 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOA];
3767 if (pTxBuffer->m_pbBuffer != NULL) { // SoA does exist
3768 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
3770 if (fEnableInvitation_p != FALSE) { // fetch target of asynchronous phase
3771 if (EplDllkInstance_g.m_bFlag2 == 0) { // own queues are empty
3772 EplDllkInstance_g.m_LastReqServiceId =
3773 kEplDllReqServiceNo;
3774 } else if (((tEplDllAsyncReqPriority) (EplDllkInstance_g.m_bFlag2 >> EPL_FRAME_FLAG2_PR_SHIFT)) == kEplDllAsyncReqPrioNmt) { // frames in own NMT request queue available
3775 EplDllkInstance_g.m_LastReqServiceId =
3776 kEplDllReqServiceNmtRequest;
3778 EplDllkInstance_g.m_LastReqServiceId =
3779 kEplDllReqServiceUnspecified;
3782 EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g.
3785 m_uiLastTargetNodeId);
3786 if (Ret != kEplSuccessful) {
3789 if (EplDllkInstance_g.m_LastReqServiceId != kEplDllReqServiceNo) { // asynchronous phase will be assigned to one node
3790 if (EplDllkInstance_g.m_uiLastTargetNodeId == EPL_C_ADR_INVALID) { // exchange invalid node ID with local node ID
3791 EplDllkInstance_g.m_uiLastTargetNodeId =
3792 EplDllkInstance_g.m_DllConfigParam.
3794 // d.k. DLL state WaitAsndTrig is not helpful;
3795 // so just step over to WaitSocTrig,
3796 // because own ASnd is sent automatically in CbFrameTransmitted() after SoA.
3797 //*pDllStateProposed_p = kEplDllMsWaitAsndTrig;
3798 *pDllStateProposed_p =
3799 kEplDllMsWaitSocTrig;
3800 } else { // assignment to CN
3801 *pDllStateProposed_p =
3806 EplDllkGetNodeInfo(EplDllkInstance_g.
3807 m_uiLastTargetNodeId);
3808 if (pNodeInfo == NULL) { // no node info structure available
3809 Ret = kEplDllNoNodeInfo;
3812 // update frame (EA, ER flags)
3813 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3816 m_bSoaFlag1 & (EPL_FRAME_FLAG1_EA
3818 EPL_FRAME_FLAG1_ER));
3819 } else { // no assignment of asynchronous phase
3820 *pDllStateProposed_p = kEplDllMsWaitSocTrig;
3821 EplDllkInstance_g.m_uiLastTargetNodeId =
3825 // update frame (target)
3826 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3828 (u8) EplDllkInstance_g.
3829 m_LastReqServiceId);
3830 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3831 m_le_bReqServiceTarget,
3832 (u8) EplDllkInstance_g.
3833 m_uiLastTargetNodeId);
3835 } else { // invite nobody
3836 // update frame (target)
3837 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3838 m_le_bReqServiceId, (u8) 0);
3839 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3840 m_le_bReqServiceTarget, (u8) 0);
3843 // update frame (NMT state)
3844 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus,
3848 Ret = EdrvSendTxMsg(pTxBuffer);
3855 //---------------------------------------------------------------------------
3857 // Function: EplDllkMnSendSoc()
3859 // Description: it updates and transmits the SoA.
3861 // Parameters: (none)
3863 // Returns: tEplKernel = error code
3868 //---------------------------------------------------------------------------
3870 static tEplKernel EplDllkMnSendSoc(void)
3872 tEplKernel Ret = kEplSuccessful;
3873 tEdrvTxBuffer *pTxBuffer = NULL;
3874 tEplFrame *pTxFrame;
3877 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOC];
3878 if (pTxBuffer->m_pbBuffer != NULL) { // SoC does exist
3879 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
3881 // $$$ update NetTime
3884 Ret = EdrvSendTxMsg(pTxBuffer);
3885 if (Ret != kEplSuccessful) {
3888 // trigger synchronous task
3889 Event.m_EventSink = kEplEventSinkSync;
3890 Event.m_EventType = kEplEventTypeSync;
3892 Ret = EplEventkPost(&Event);
3899 //---------------------------------------------------------------------------
3901 // Function: EplDllkMnSendPreq()
3903 // Description: it updates and transmits the PReq for the next isochronous CN
3904 // or own PRes if enabled.
3906 // Parameters: NmtState_p = current NMT state
3907 // pDllStateProposed_p = proposed DLL state
3909 // Returns: tEplKernel = error code
3914 //---------------------------------------------------------------------------
3916 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
3917 tEplDllState * pDllStateProposed_p)
3919 tEplKernel Ret = kEplSuccessful;
3920 tEdrvTxBuffer *pTxBuffer = NULL;
3921 tEplFrame *pTxFrame;
3924 if (EplDllkInstance_g.m_pCurNodeInfo == NULL) { // start with first isochronous CN
3925 EplDllkInstance_g.m_pCurNodeInfo =
3926 EplDllkInstance_g.m_pFirstNodeInfo;
3927 } else { // iterate to next isochronous CN
3928 EplDllkInstance_g.m_pCurNodeInfo =
3929 EplDllkInstance_g.m_pCurNodeInfo->m_pNextNodeInfo;
3932 if (EplDllkInstance_g.m_pCurNodeInfo == NULL) { // last isochronous CN reached
3933 Ret = EplDllkMnSendSoa(NmtState_p, pDllStateProposed_p, TRUE);
3936 pTxBuffer = EplDllkInstance_g.m_pCurNodeInfo->m_pPreqTxBuffer;
3938 EplDllkInstance_g.m_pCurNodeInfo->
3939 m_bSoaFlag1 & EPL_FRAME_FLAG1_EA;
3940 *pDllStateProposed_p = kEplDllMsWaitPres;
3943 // $$$ d.k.: maybe move this call to CbFrameTransmitted(), because the time should run from there
3944 #if EPL_TIMER_USE_HIGHRES != FALSE
3946 EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.
3951 EplDllkCbMnTimerResponse, 0L,
3956 if (pTxBuffer == NULL) { // PReq does not exist
3957 Ret = kEplDllTxBufNotReady;
3961 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
3963 if (pTxFrame != NULL) { // PReq does exist
3964 if (NmtState_p == kEplNmtMsOperational) { // leave RD flag untouched
3966 AmiGetByteFromLe(&pTxFrame->m_Data.m_Preq.
3967 m_le_bFlag1) & EPL_FRAME_FLAG1_RD;
3970 if (pTxBuffer == &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]) { // PRes of MN will be sent
3972 AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus,
3974 *pDllStateProposed_p = kEplDllMsWaitSoaTrig;
3976 // $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary
3977 // update frame (Flag1)
3978 AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, bFlag1);
3980 // calculate frame size from payload size
3981 pTxBuffer->m_uiTxMsgLen =
3982 AmiGetWordFromLe(&pTxFrame->m_Data.m_Preq.m_le_wSize) + 24;
3985 Ret = EdrvSendTxMsg(pTxBuffer);
3987 Ret = kEplDllTxFrameInvalid;
3994 //---------------------------------------------------------------------------
3996 // Function: EplDllkAsyncFrameNotReceived()
3998 // Description: passes empty ASnd frame to receive FIFO.
3999 // It will be called only for frames with registered AsndServiceIds
4000 // (only kEplDllAsndFilterAny).
4004 // Returns: tEplKernel = error code
4009 //---------------------------------------------------------------------------
4011 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
4013 unsigned int uiNodeId_p)
4015 tEplKernel Ret = kEplSuccessful;
4017 tEplFrame *pFrame = (tEplFrame *) abBuffer;
4018 tEplFrameInfo FrameInfo;
4020 // check if previous SoA invitation was not answered
4021 switch (ReqServiceId_p) {
4022 case kEplDllReqServiceIdent:
4023 case kEplDllReqServiceStatus:
4024 // ASnd service registered?
4025 if (EplDllkInstance_g.m_aAsndFilter[ReqServiceId_p] == kEplDllAsndFilterAny) { // ASnd service ID is registered
4026 AmiSetByteToLe(&pFrame->m_le_bSrcNodeId,
4029 AmiSetByteToLe(&pFrame->m_le_bMessageType,
4030 (u8) kEplMsgTypeAsnd);
4032 AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
4033 (u8) ReqServiceId_p);
4034 // create frame info structure
4035 FrameInfo.m_pFrame = pFrame;
4036 FrameInfo.m_uiFrameSize = 18; // empty non existing ASnd frame
4037 // forward frame via async receive FIFO to userspace
4038 Ret = EplDllkCalAsyncFrameReceived(&FrameInfo);
4042 // no invitation issued or it was successfully answered or it is uninteresting
4049 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
4051 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)