2008-12-19 20:41:57 +01:00
/****************************************************************************
( c ) SYSTEC electronic GmbH , D - 07 973 Greiz , August - Bebel - Str . 29
www . systec - electronic . com
Project : openPOWERLINK
Description : source file for kernel DLL module
License :
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
3. Neither the name of SYSTEC electronic GmbH nor the names of its
contributors may be used to endorse or promote products derived
from this software without prior written permission . For written
permission , please contact info @ systec - electronic . com .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
" AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE .
Severability Clause :
If a provision of this License is or becomes illegal , invalid or
unenforceable in any jurisdiction , that shall not affect :
1. the validity or enforceability in that jurisdiction of any other
provision of this License ; or
2. the validity or enforceability in other jurisdictions of that or
any other provision of this License .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ RCSfile : EplDllk . c , v $
$ Author : D . Krueger $
$ Revision : 1.21 $ $ Date : 2008 / 11 / 13 17 : 13 : 09 $
$ State : Exp $
Build Environment :
GCC V3 .4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History :
2006 / 06 / 12 d . k . : start of the implementation , version 1.00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "kernel/EplDllk.h"
# include "kernel/EplDllkCal.h"
# include "kernel/EplEventk.h"
# include "kernel/EplNmtk.h"
# include "edrv.h"
# include "Benchmark.h"
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
# include "kernel/EplPdok.h"
# endif
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
# include "kernel/VirtualEthernet.h"
# endif
//#if EPL_TIMER_USE_HIGHRES != FALSE
# include "kernel/EplTimerHighResk.h"
//#endif
# if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
# if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0)
# error "EPL module DLLK needs EPL module NMTK!"
# endif
# if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) && (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
# error "EPL module DLLK: select only one of EPL_DLL_PRES_READY_AFTER_SOA and EPL_DLL_PRES_READY_AFTER_SOC."
# endif
# if ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) \
& & ( ( ( EPL_MODULE_INTEGRATION ) & ( EPL_MODULE_NMT_MN ) ) = = 0 )
# error "EPL module DLLK: currently, EPL_DLL_PRES_READY_AFTER_* is not supported if EPL_MODULE_NMT_MN is enabled."
# endif
# if (EDRV_FAST_TXFRAMES == FALSE) && \
( ( EPL_DLL_PRES_READY_AFTER_SOA ! = FALSE ) | | ( EPL_DLL_PRES_READY_AFTER_SOC ! = FALSE ) )
# error "EPL module DLLK: EPL_DLL_PRES_READY_AFTER_* is enabled, but not EDRV_FAST_TXFRAMES."
# endif
/***************************************************************************/
/* */
/* */
/* G L O B A L D E F I N I T I O N S */
/* */
/* */
/***************************************************************************/
//---------------------------------------------------------------------------
// const defines
//---------------------------------------------------------------------------
// TracePoint support for realtime-debugging
# ifdef _DBG_TRACE_POINTS_
2008-12-20 02:11:52 +01:00
void PUBLIC TgtDbgSignalTracePoint ( BYTE bTracePointNumber_p ) ;
void PUBLIC TgtDbgPostTraceValue ( DWORD dwTraceValue_p ) ;
# define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
# define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
2008-12-19 20:41:57 +01:00
# else
2008-12-20 02:11:52 +01:00
# define TGT_DBG_SIGNAL_TRACE_POINT(p)
# define TGT_DBG_POST_TRACE_VALUE(v)
2008-12-19 20:41:57 +01:00
# endif
# define EPL_DLLK_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
TGT_DBG_POST_TRACE_VALUE ( ( kEplEventSinkDllk < < 28 ) | ( Event_p < < 24 ) \
| ( uiNodeId_p < < 16 ) | wErrorCode_p )
/***************************************************************************/
/* */
/* */
/* C L A S S EplDllk */
/* */
/* */
/***************************************************************************/
//
// Description:
//
//
/***************************************************************************/
//=========================================================================//
// //
// P R I V A T E D E F I N I T I O N S //
// //
//=========================================================================//
//---------------------------------------------------------------------------
// const defines
//---------------------------------------------------------------------------
// defines for indexes of tEplDllInstance.m_pTxFrameInfo
2008-12-20 02:11:52 +01:00
# define EPL_DLLK_TXFRAME_IDENTRES 0 // IdentResponse on CN / MN
# define EPL_DLLK_TXFRAME_STATUSRES 1 // StatusResponse on CN / MN
# define EPL_DLLK_TXFRAME_NMTREQ 2 // NMT Request from FIFO on CN / MN
# define EPL_DLLK_TXFRAME_NONEPL 3 // non-EPL frame from FIFO on CN / MN
# define EPL_DLLK_TXFRAME_PRES 4 // PRes on CN / MN
# define EPL_DLLK_TXFRAME_SOC 5 // SoC on MN
# define EPL_DLLK_TXFRAME_SOA 6 // SoA on MN
# define EPL_DLLK_TXFRAME_PREQ 7 // PReq on MN
2008-12-19 20:41:57 +01:00
# if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
# define EPL_DLLK_TXFRAME_COUNT (7 + EPL_D_NMT_MaxCNNumber_U8 + 2) // on MN: 7 + MaxPReq of regular CNs + 1 Diag + 1 Router
2008-12-19 20:41:57 +01:00
# else
2008-12-20 02:11:52 +01:00
# define EPL_DLLK_TXFRAME_COUNT 5 // on CN: 5
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
# define EPL_DLLK_BUFLEN_EMPTY 0 // buffer is empty
# define EPL_DLLK_BUFLEN_FILLING 1 // just the buffer is being filled
# define EPL_DLLK_BUFLEN_MIN 60 // minimum ethernet frame length
2008-12-19 20:41:57 +01:00
//---------------------------------------------------------------------------
// local types
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
typedef enum {
kEplDllGsInit = 0x00 , // MN/CN: initialisation (< PreOp2)
kEplDllCsWaitPreq = 0x01 , // CN: wait for PReq frame
kEplDllCsWaitSoc = 0x02 , // CN: wait for SoC frame
kEplDllCsWaitSoa = 0x03 , // CN: wait for SoA frame
kEplDllMsNonCyclic = 0x04 , // MN: reduced EPL cycle (PreOp1)
kEplDllMsWaitSocTrig = 0x05 , // MN: wait for SoC trigger (cycle timer)
kEplDllMsWaitPreqTrig = 0x06 , // MN: wait for (first) PReq trigger (WaitSoCPReq_U32)
kEplDllMsWaitPres = 0x07 , // MN: wait for PRes frame from CN
kEplDllMsWaitSoaTrig = 0x08 , // MN: wait for SoA trigger (PRes transmitted)
kEplDllMsWaitAsndTrig = 0x09 , // MN: wait for ASnd trigger (SoA transmitted)
kEplDllMsWaitAsnd = 0x0A , // MN: wait for ASnd frame if SoA contained invitation
2008-12-19 20:41:57 +01:00
} tEplDllState ;
2008-12-20 02:11:52 +01:00
typedef struct {
BYTE m_be_abSrcMac [ 6 ] ;
tEdrvTxBuffer * m_pTxBuffer ; // Buffers for Tx-Frames
unsigned int m_uiMaxTxFrames ;
BYTE m_bFlag1 ; // Flag 1 with EN, EC for PRes, StatusRes
BYTE m_bMnFlag1 ; // Flag 1 with EA, ER from PReq, SoA of MN
BYTE m_bFlag2 ; // Flag 2 with PR and RS for PRes, StatusRes, IdentRes
tEplDllConfigParam m_DllConfigParam ;
tEplDllIdentParam m_DllIdentParam ;
tEplDllState m_DllState ;
tEplDllkCbAsync m_pfnCbAsync ;
tEplDllAsndFilter m_aAsndFilter [ EPL_DLL_MAX_ASND_SERVICE_ID ] ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
tEplDllkNodeInfo * m_pFirstNodeInfo ;
tEplDllkNodeInfo * m_pCurNodeInfo ;
tEplDllkNodeInfo m_aNodeInfo [ EPL_NMT_MAX_NODE_ID ] ;
tEplDllReqServiceId m_LastReqServiceId ;
unsigned int m_uiLastTargetNodeId ;
2008-12-19 20:41:57 +01:00
# endif
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
tEplTimerHdl m_TimerHdlCycle ; // used for EPL cycle monitoring on CN and generation on MN
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
tEplTimerHdl m_TimerHdlResponse ; // used for CN response monitoring
# endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
unsigned int m_uiCycleCount ; // cycle counter (needed for multiplexed cycle support)
unsigned long long m_ullFrameTimeout ; // frame timeout (cycle length + loss of frame tolerance)
2008-12-19 20:41:57 +01:00
} tEplDllkInstance ;
//---------------------------------------------------------------------------
// local vars
//---------------------------------------------------------------------------
// if no dynamic memory allocation shall be used
// define structures statically
2008-12-20 02:11:52 +01:00
static tEplDllkInstance EplDllkInstance_g ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
static tEdrvTxBuffer aEplDllkTxBuffer_l [ EPL_DLLK_TXFRAME_COUNT ] ;
2008-12-19 20:41:57 +01:00
//---------------------------------------------------------------------------
// local function prototypes
//---------------------------------------------------------------------------
// change DLL state on event
2008-12-20 02:11:52 +01:00
static tEplKernel EplDllkChangeState ( tEplNmtEvent NmtEvent_p ,
tEplNmtState NmtState_p ) ;
2008-12-19 20:41:57 +01:00
// called from EdrvInterruptHandler()
static void EplDllkCbFrameReceived ( tEdrvRxBuffer * pRxBuffer_p ) ;
// called from EdrvInterruptHandler()
static void EplDllkCbFrameTransmitted ( tEdrvTxBuffer * pTxBuffer_p ) ;
// check frame and set missing information
2008-12-20 02:11:52 +01:00
static tEplKernel EplDllkCheckFrame ( tEplFrame * pFrame_p ,
unsigned int uiFrameSize_p ) ;
2008-12-19 20:41:57 +01:00
// called by high resolution timer module to monitor EPL cycle as CN
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
static tEplKernel PUBLIC EplDllkCbCnTimer ( tEplTimerEventArg * pEventArg_p ) ;
2008-12-19 20:41:57 +01:00
# endif
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
// MN: returns internal node info structure
2008-12-20 02:11:52 +01:00
static tEplDllkNodeInfo * EplDllkGetNodeInfo ( unsigned int uiNodeId_p ) ;
2008-12-19 20:41:57 +01:00
// transmit SoA
static tEplKernel EplDllkMnSendSoa ( tEplNmtState NmtState_p ,
2008-12-20 02:11:52 +01:00
tEplDllState * pDllStateProposed_p ,
BOOL fEnableInvitation_p ) ;
2008-12-19 20:41:57 +01:00
static tEplKernel EplDllkMnSendSoc ( void ) ;
static tEplKernel EplDllkMnSendPreq ( tEplNmtState NmtState_p ,
2008-12-20 02:11:52 +01:00
tEplDllState * pDllStateProposed_p ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
static tEplKernel EplDllkAsyncFrameNotReceived ( tEplDllReqServiceId
ReqServiceId_p ,
unsigned int uiNodeId_p ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
static tEplKernel PUBLIC EplDllkCbMnTimerCycle ( tEplTimerEventArg * pEventArg_p ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
static tEplKernel PUBLIC EplDllkCbMnTimerResponse ( tEplTimerEventArg *
pEventArg_p ) ;
2008-12-19 20:41:57 +01:00
# endif
//=========================================================================//
// //
// P U B L I C F U N C T I O N S //
// //
//=========================================================================//
//---------------------------------------------------------------------------
//
// Function: EplDllkAddInstance()
//
// Description: add and initialize new instance of EPL stack
//
// Parameters: pInitParam_p = initialisation parameters like MAC address
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkAddInstance ( tEplDllkInitParam * pInitParam_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
unsigned int uiIndex ;
tEdrvInitParam EdrvInitParam ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// reset instance structure
EPL_MEMSET ( & EplDllkInstance_g , 0 , sizeof ( EplDllkInstance_g ) ) ;
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret = EplTimerHighReskInit ( ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while initializing high resolution timer module
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// if dynamic memory allocation available
// allocate instance structure
// allocate TPDO and RPDO table with default size
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// initialize and link pointers in instance structure to frame tables
EplDllkInstance_g . m_pTxBuffer = aEplDllkTxBuffer_l ;
EplDllkInstance_g . m_uiMaxTxFrames =
sizeof ( aEplDllkTxBuffer_l ) / sizeof ( tEdrvTxBuffer ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// initialize state
EplDllkInstance_g . m_DllState = kEplDllGsInit ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
// set up node info structure
for ( uiIndex = 0 ; uiIndex < tabentries ( EplDllkInstance_g . m_aNodeInfo ) ;
uiIndex + + ) {
EplDllkInstance_g . m_aNodeInfo [ uiIndex ] . m_uiNodeId = uiIndex + 1 ;
EplDllkInstance_g . m_aNodeInfo [ uiIndex ] . m_wPresPayloadLimit =
0xFFFF ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// initialize Edrv
EPL_MEMCPY ( EdrvInitParam . m_abMyMacAddr , pInitParam_p - > m_be_abSrcMac , 6 ) ;
EdrvInitParam . m_pfnRxHandler = EplDllkCbFrameReceived ;
EdrvInitParam . m_pfnTxHandler = EplDllkCbFrameTransmitted ;
Ret = EdrvInit ( & EdrvInitParam ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while initializing ethernet driver
goto Exit ;
}
// copy local MAC address from Ethernet driver back to local instance structure
// because Ethernet driver may have read it from controller EEPROM
EPL_MEMCPY ( EplDllkInstance_g . m_be_abSrcMac , EdrvInitParam . m_abMyMacAddr ,
6 ) ;
EPL_MEMCPY ( pInitParam_p - > m_be_abSrcMac , EdrvInitParam . m_abMyMacAddr , 6 ) ;
// initialize TxBuffer array
for ( uiIndex = 0 ; uiIndex < EplDllkInstance_g . m_uiMaxTxFrames ;
uiIndex + + ) {
EplDllkInstance_g . m_pTxBuffer [ uiIndex ] . m_pbBuffer = NULL ;
}
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
2008-12-20 02:11:52 +01:00
Ret = VEthAddInstance ( pInitParam_p ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkDelInstance()
//
// Description: deletes an instance of EPL stack
//
// Parameters: (none)
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkDelInstance ( void )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// reset state
EplDllkInstance_g . m_DllState = kEplDllGsInit ;
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret = EplTimerHighReskDelInstance ( ) ;
2008-12-19 20:41:57 +01:00
# endif
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
2008-12-20 02:11:52 +01:00
Ret = VEthDelInstance ( ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
Ret = EdrvShutdown ( ) ;
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCreateTxFrame
//
// Description: creates the buffer for a Tx frame and registers it to the
// ethernet driver
//
// Parameters: puiHandle_p = OUT: handle to frame buffer
// ppFrame_p = OUT: pointer to pointer of EPL frame
// puiFrameSize_p = IN/OUT: pointer to size of frame
// returned size is always equal or larger than
// requested size, if that is not possible
// an error will be returned
// MsgType_p = EPL message type
// ServiceId_p = Service ID in case of ASnd frame, otherwise
// kEplDllAsndNotDefined
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
tEplKernel EplDllkCreateTxFrame ( unsigned int * puiHandle_p ,
tEplFrame * * ppFrame_p ,
unsigned int * puiFrameSize_p ,
tEplMsgType MsgType_p ,
tEplDllAsndServiceId ServiceId_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplFrame * pTxFrame ;
unsigned int uiHandle = EplDllkInstance_g . m_uiMaxTxFrames ;
tEdrvTxBuffer * pTxBuffer = NULL ;
if ( MsgType_p = = kEplMsgTypeAsnd ) {
// search for fixed Tx buffers
if ( ServiceId_p = = kEplDllAsndIdentResponse ) {
uiHandle = EPL_DLLK_TXFRAME_IDENTRES ;
} else if ( ServiceId_p = = kEplDllAsndStatusResponse ) {
uiHandle = EPL_DLLK_TXFRAME_STATUSRES ;
} else if ( ( ServiceId_p = = kEplDllAsndNmtRequest )
| | ( ServiceId_p = = kEplDllAsndNmtCommand ) ) {
uiHandle = EPL_DLLK_TXFRAME_NMTREQ ;
}
if ( uiHandle > = EplDllkInstance_g . m_uiMaxTxFrames ) { // look for free entry
uiHandle = EPL_DLLK_TXFRAME_PREQ ;
pTxBuffer = & EplDllkInstance_g . m_pTxBuffer [ uiHandle ] ;
for ( ; uiHandle < EplDllkInstance_g . m_uiMaxTxFrames ;
uiHandle + + , pTxBuffer + + ) {
if ( pTxBuffer - > m_pbBuffer = = NULL ) { // free entry found
break ;
}
}
}
} else if ( MsgType_p = = kEplMsgTypeNonEpl ) {
uiHandle = EPL_DLLK_TXFRAME_NONEPL ;
} else if ( MsgType_p = = kEplMsgTypePres ) {
uiHandle = EPL_DLLK_TXFRAME_PRES ;
} else if ( MsgType_p = = kEplMsgTypeSoc ) {
uiHandle = EPL_DLLK_TXFRAME_SOC ;
} else if ( MsgType_p = = kEplMsgTypeSoa ) {
uiHandle = EPL_DLLK_TXFRAME_SOA ;
} else { // look for free entry
uiHandle = EPL_DLLK_TXFRAME_PREQ ;
pTxBuffer = & EplDllkInstance_g . m_pTxBuffer [ uiHandle ] ;
for ( ; uiHandle < EplDllkInstance_g . m_uiMaxTxFrames ;
uiHandle + + , pTxBuffer + + ) {
if ( pTxBuffer - > m_pbBuffer = = NULL ) { // free entry found
break ;
}
}
if ( pTxBuffer - > m_pbBuffer ! = NULL ) {
Ret = kEplEdrvNoFreeBufEntry ;
goto Exit ;
}
}
// test if requested entry is free
pTxBuffer = & EplDllkInstance_g . m_pTxBuffer [ uiHandle ] ;
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // entry is not free
Ret = kEplEdrvNoFreeBufEntry ;
goto Exit ;
}
// setup Tx buffer
pTxBuffer - > m_EplMsgType = MsgType_p ;
pTxBuffer - > m_uiMaxBufferLen = * puiFrameSize_p ;
Ret = EdrvAllocTxMsgBuffer ( pTxBuffer ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
// because buffer size may be larger than requested
// memorize real length of frame
pTxBuffer - > m_uiTxMsgLen = * puiFrameSize_p ;
// fill whole frame with 0
EPL_MEMSET ( pTxBuffer - > m_pbBuffer , 0 , pTxBuffer - > m_uiMaxBufferLen ) ;
pTxFrame = ( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
if ( MsgType_p ! = kEplMsgTypeNonEpl ) { // fill out Frame only if it is an EPL frame
// ethertype
AmiSetWordToBe ( & pTxFrame - > m_be_wEtherType ,
EPL_C_DLL_ETHERTYPE_EPL ) ;
// source node ID
AmiSetByteToLe ( & pTxFrame - > m_le_bSrcNodeId ,
( BYTE ) EplDllkInstance_g . m_DllConfigParam .
m_uiNodeId ) ;
// source MAC address
EPL_MEMCPY ( & pTxFrame - > m_be_abSrcMac [ 0 ] ,
& EplDllkInstance_g . m_be_abSrcMac [ 0 ] , 6 ) ;
switch ( MsgType_p ) {
case kEplMsgTypeAsnd :
// destination MAC address
AmiSetQword48ToBe ( & pTxFrame - > m_be_abDstMac [ 0 ] ,
EPL_C_DLL_MULTICAST_ASND ) ;
// destination node ID
switch ( ServiceId_p ) {
case kEplDllAsndIdentResponse :
case kEplDllAsndStatusResponse :
{ // IdentResponses and StatusResponses are Broadcast
AmiSetByteToLe ( & pTxFrame - >
m_le_bDstNodeId ,
( BYTE )
EPL_C_ADR_BROADCAST ) ;
break ;
}
default :
break ;
}
// ASnd Service ID
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd . m_le_bServiceId ,
ServiceId_p ) ;
break ;
case kEplMsgTypeSoc :
// destination MAC address
AmiSetQword48ToBe ( & pTxFrame - > m_be_abDstMac [ 0 ] ,
EPL_C_DLL_MULTICAST_SOC ) ;
// destination node ID
AmiSetByteToLe ( & pTxFrame - > m_le_bDstNodeId ,
( BYTE ) EPL_C_ADR_BROADCAST ) ;
// reset Flags
//AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (BYTE) 0);
//AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (BYTE) 0);
break ;
case kEplMsgTypeSoa :
// destination MAC address
AmiSetQword48ToBe ( & pTxFrame - > m_be_abDstMac [ 0 ] ,
EPL_C_DLL_MULTICAST_SOA ) ;
// destination node ID
AmiSetByteToLe ( & pTxFrame - > m_le_bDstNodeId ,
( BYTE ) EPL_C_ADR_BROADCAST ) ;
// reset Flags
//AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (BYTE) 0);
//AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (BYTE) 0);
// EPL profile version
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa . m_le_bEplVersion ,
( BYTE ) EPL_SPEC_VERSION ) ;
break ;
case kEplMsgTypePres :
// destination MAC address
AmiSetQword48ToBe ( & pTxFrame - > m_be_abDstMac [ 0 ] ,
EPL_C_DLL_MULTICAST_PRES ) ;
// destination node ID
AmiSetByteToLe ( & pTxFrame - > m_le_bDstNodeId ,
( BYTE ) EPL_C_ADR_BROADCAST ) ;
// reset Flags
//AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (BYTE) 0);
//AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (BYTE) 0);
// PDO size
//AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0);
break ;
case kEplMsgTypePreq :
// reset Flags
//AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (BYTE) 0);
//AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (BYTE) 0);
// PDO size
//AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0);
break ;
default :
break ;
}
// EPL message type
AmiSetByteToLe ( & pTxFrame - > m_le_bMessageType , ( BYTE ) MsgType_p ) ;
}
* ppFrame_p = pTxFrame ;
* puiFrameSize_p = pTxBuffer - > m_uiMaxBufferLen ;
* puiHandle_p = uiHandle ;
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkDeleteTxFrame
//
// Description: deletes the buffer for a Tx frame and frees it in the
// ethernet driver
//
// Parameters: uiHandle_p = IN: handle to frame buffer
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
tEplKernel EplDllkDeleteTxFrame ( unsigned int uiHandle_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEdrvTxBuffer * pTxBuffer = NULL ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( uiHandle_p > = EplDllkInstance_g . m_uiMaxTxFrames ) { // handle is not valid
Ret = kEplDllIllegalHdl ;
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
pTxBuffer = & EplDllkInstance_g . m_pTxBuffer [ uiHandle_p ] ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// mark buffer as free so that frame will not be send in future anymore
// $$$ d.k. What's up with running transmissions?
pTxBuffer - > m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY ;
pTxBuffer - > m_pbBuffer = NULL ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// delete Tx buffer
Ret = EdrvReleaseTxMsgBuffer ( pTxBuffer ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while releasing Tx frame
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkProcess
//
// Description: process the passed event
//
// Parameters: pEvent_p = event to be processed
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkProcess ( tEplEvent * pEvent_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplFrame * pTxFrame ;
tEdrvTxBuffer * pTxBuffer ;
unsigned int uiHandle ;
unsigned int uiFrameSize ;
BYTE abMulticastMac [ 6 ] ;
tEplDllAsyncReqPriority AsyncReqPriority ;
unsigned int uiFrameCount ;
tEplNmtState NmtState ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2008-12-20 02:11:52 +01:00
tEplFrameInfo FrameInfo ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
switch ( pEvent_p - > m_EventType ) {
case kEplEventTypeDllkCreate :
{
// $$$ reset ethernet driver
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
NmtState = * ( ( tEplNmtState * ) pEvent_p - > m_pArg ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// initialize flags for PRes and StatusRes
EplDllkInstance_g . m_bFlag1 = EPL_FRAME_FLAG1_EC ;
EplDllkInstance_g . m_bMnFlag1 = 0 ;
EplDllkInstance_g . m_bFlag2 = 0 ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
// initialize linked node list
EplDllkInstance_g . m_pFirstNodeInfo = NULL ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// register TxFrames in Edrv
// IdentResponse
uiFrameSize = EPL_C_DLL_MINSIZE_IDENTRES ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize , kEplMsgTypeAsnd ,
kEplDllAsndIdentResponse ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
// EPL profile version
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_bEplProfileVersion ,
( BYTE ) EPL_SPEC_VERSION ) ;
// FeatureFlags
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwFeatureFlags ,
EplDllkInstance_g . m_DllConfigParam .
m_dwFeatureFlags ) ;
// MTU
AmiSetWordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_wMtu ,
( WORD ) EplDllkInstance_g .
m_DllConfigParam . m_uiAsyncMtu ) ;
// PollInSize
AmiSetWordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_wPollInSize ,
( WORD ) EplDllkInstance_g .
m_DllConfigParam .
m_uiPreqActPayloadLimit ) ;
// PollOutSize
AmiSetWordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_wPollOutSize ,
( WORD ) EplDllkInstance_g .
m_DllConfigParam .
m_uiPresActPayloadLimit ) ;
// ResponseTime / PresMaxLatency
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwResponseTime ,
EplDllkInstance_g . m_DllConfigParam .
m_dwPresMaxLatency ) ;
// DeviceType
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwDeviceType ,
EplDllkInstance_g . m_DllIdentParam .
m_dwDeviceType ) ;
// VendorId
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwVendorId ,
EplDllkInstance_g . m_DllIdentParam .
m_dwVendorId ) ;
// ProductCode
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwProductCode ,
EplDllkInstance_g . m_DllIdentParam .
m_dwProductCode ) ;
// RevisionNumber
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwRevisionNumber ,
EplDllkInstance_g . m_DllIdentParam .
m_dwRevisionNumber ) ;
// SerialNumber
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwSerialNumber ,
EplDllkInstance_g . m_DllIdentParam .
m_dwSerialNumber ) ;
// VendorSpecificExt1
AmiSetQword64ToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse .
m_le_qwVendorSpecificExt1 ,
EplDllkInstance_g . m_DllIdentParam .
m_qwVendorSpecificExt1 ) ;
// VerifyConfigurationDate
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse .
m_le_dwVerifyConfigurationDate ,
EplDllkInstance_g . m_DllIdentParam .
m_dwVerifyConfigurationDate ) ;
// VerifyConfigurationTime
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse .
m_le_dwVerifyConfigurationTime ,
EplDllkInstance_g . m_DllIdentParam .
m_dwVerifyConfigurationTime ) ;
// ApplicationSwDate
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse .
m_le_dwApplicationSwDate ,
EplDllkInstance_g . m_DllIdentParam .
m_dwApplicationSwDate ) ;
// ApplicationSwTime
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse .
m_le_dwApplicationSwTime ,
EplDllkInstance_g . m_DllIdentParam .
m_dwApplicationSwTime ) ;
// IPAddress
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwIpAddress ,
EplDllkInstance_g . m_DllIdentParam .
m_dwIpAddress ) ;
// SubnetMask
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwSubnetMask ,
EplDllkInstance_g . m_DllIdentParam .
m_dwSubnetMask ) ;
// DefaultGateway
AmiSetDwordToLe ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_dwDefaultGateway ,
EplDllkInstance_g . m_DllIdentParam .
m_dwDefaultGateway ) ;
// HostName
EPL_MEMCPY ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_sHostname [ 0 ] ,
& EplDllkInstance_g . m_DllIdentParam .
m_sHostname [ 0 ] ,
sizeof ( EplDllkInstance_g . m_DllIdentParam .
m_sHostname ) ) ;
// VendorSpecificExt2
EPL_MEMCPY ( & pTxFrame - > m_Data . m_Asnd . m_Payload .
m_IdentResponse . m_le_abVendorSpecificExt2 [ 0 ] ,
& EplDllkInstance_g . m_DllIdentParam .
m_abVendorSpecificExt2 [ 0 ] ,
sizeof ( EplDllkInstance_g . m_DllIdentParam .
m_abVendorSpecificExt2 ) ) ;
// StatusResponse
uiFrameSize = EPL_C_DLL_MINSIZE_STATUSRES ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize , kEplMsgTypeAsnd ,
kEplDllAsndStatusResponse ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
// PRes $$$ maybe move this to PDO module
if ( ( EplDllkInstance_g . m_DllConfigParam . m_fAsyncOnly = =
FALSE )
& & ( EplDllkInstance_g . m_DllConfigParam . m_uiPresActPayloadLimit > = 36 ) ) { // it is not configured as async-only CN,
// so take part in isochronous phase and register PRes frame
uiFrameSize =
EplDllkInstance_g . m_DllConfigParam .
m_uiPresActPayloadLimit + 24 ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize ,
kEplMsgTypePres ,
kEplDllAsndNotDefined ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2008-12-20 02:11:52 +01:00
// initially encode TPDO -> inform PDO module
FrameInfo . m_pFrame = pTxFrame ;
FrameInfo . m_uiFrameSize = uiFrameSize ;
Ret = EplPdokCbPdoTransmitted ( & FrameInfo ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// reset cycle counter
EplDllkInstance_g . m_uiCycleCount = 0 ;
} else { // it is an async-only CN
// fool EplDllkChangeState() to think that PRes was not expected
EplDllkInstance_g . m_uiCycleCount = 1 ;
}
// NMT request
uiFrameSize = EPL_C_IP_MAX_MTU ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize , kEplMsgTypeAsnd ,
kEplDllAsndNmtRequest ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
// mark Tx buffer as empty
EplDllkInstance_g . m_pTxBuffer [ uiHandle ] . m_uiTxMsgLen =
EPL_DLLK_BUFLEN_EMPTY ;
// non-EPL frame
uiFrameSize = EPL_C_IP_MAX_MTU ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize ,
kEplMsgTypeNonEpl ,
kEplDllAsndNotDefined ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
// mark Tx buffer as empty
EplDllkInstance_g . m_pTxBuffer [ uiHandle ] . m_uiTxMsgLen =
EPL_DLLK_BUFLEN_EMPTY ;
// register multicast MACs in ethernet driver
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_SOC ) ;
Ret = EdrvDefineRxMacAddrEntry ( abMulticastMac ) ;
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_SOA ) ;
Ret = EdrvDefineRxMacAddrEntry ( abMulticastMac ) ;
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_PRES ) ;
Ret = EdrvDefineRxMacAddrEntry ( abMulticastMac ) ;
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_ASND ) ;
Ret = EdrvDefineRxMacAddrEntry ( abMulticastMac ) ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
if ( NmtState > = kEplNmtMsNotActive ) { // local node is MN
unsigned int uiIndex ;
// SoC
uiFrameSize = EPL_C_DLL_MINSIZE_SOC ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize ,
kEplMsgTypeSoc ,
kEplDllAsndNotDefined ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
// SoA
uiFrameSize = EPL_C_DLL_MINSIZE_SOA ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pTxFrame ,
& uiFrameSize ,
kEplMsgTypeSoa ,
kEplDllAsndNotDefined ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while registering Tx frame
goto Exit ;
}
for ( uiIndex = 0 ;
uiIndex <
tabentries ( EplDllkInstance_g . m_aNodeInfo ) ;
uiIndex + + ) {
2008-12-19 20:41:57 +01:00
// EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
2008-12-20 02:11:52 +01:00
EplDllkInstance_g . m_aNodeInfo [ uiIndex ] .
m_wPresPayloadLimit =
( WORD ) EplDllkInstance_g .
m_DllConfigParam .
m_uiIsochrRxMaxPayload ;
}
// calculate cycle length
EplDllkInstance_g . m_ullFrameTimeout = 1000LL
*
( ( unsigned long long ) EplDllkInstance_g .
m_DllConfigParam . m_dwCycleLen ) ;
}
2008-12-19 20:41:57 +01:00
# endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
Ret = EplDllkCalAsyncClearBuffer ( ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
break ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
case kEplEventTypeDllkDestroy :
{
// destroy all data structures
NmtState = * ( ( tEplNmtState * ) pEvent_p - > m_pArg ) ;
// delete Tx frames
Ret = EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_IDENTRES ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Ret = EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_STATUSRES ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
Ret = EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_PRES ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
Ret = EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_NMTREQ ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
Ret = EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_NONEPL ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
if ( NmtState > = kEplNmtMsNotActive ) { // local node was MN
unsigned int uiIndex ;
Ret =
EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_SOC ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
Ret =
EplDllkDeleteTxFrame ( EPL_DLLK_TXFRAME_SOA ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
for ( uiIndex = 0 ;
uiIndex <
tabentries ( EplDllkInstance_g . m_aNodeInfo ) ;
uiIndex + + ) {
if ( EplDllkInstance_g .
m_aNodeInfo [ uiIndex ] .
m_pPreqTxBuffer ! = NULL ) {
uiHandle =
EplDllkInstance_g .
m_aNodeInfo [ uiIndex ] .
m_pPreqTxBuffer -
EplDllkInstance_g .
m_pTxBuffer ;
EplDllkInstance_g .
m_aNodeInfo [ uiIndex ] .
m_pPreqTxBuffer = NULL ;
Ret =
EplDllkDeleteTxFrame
( uiHandle ) ;
if ( Ret ! = kEplSuccessful ) { // error occured while deregistering Tx frame
goto Exit ;
}
}
EplDllkInstance_g . m_aNodeInfo [ uiIndex ] .
m_wPresPayloadLimit = 0xFFFF ;
}
}
2008-12-19 20:41:57 +01:00
# endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
// deregister multicast MACs in ethernet driver
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_SOC ) ;
Ret = EdrvUndefineRxMacAddrEntry ( abMulticastMac ) ;
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_SOA ) ;
Ret = EdrvUndefineRxMacAddrEntry ( abMulticastMac ) ;
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_PRES ) ;
Ret = EdrvUndefineRxMacAddrEntry ( abMulticastMac ) ;
AmiSetQword48ToBe ( & abMulticastMac [ 0 ] ,
EPL_C_DLL_MULTICAST_ASND ) ;
Ret = EdrvUndefineRxMacAddrEntry ( abMulticastMac ) ;
// delete timer
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret =
EplTimerHighReskDeleteTimer ( & EplDllkInstance_g .
m_TimerHdlCycle ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
break ;
}
case kEplEventTypeDllkFillTx :
{
// fill TxBuffer of specified priority with new frame if empty
pTxFrame = NULL ;
AsyncReqPriority =
* ( ( tEplDllAsyncReqPriority * ) pEvent_p - > m_pArg ) ;
switch ( AsyncReqPriority ) {
case kEplDllAsyncReqPrioNmt : // NMT request priority
{
pTxBuffer =
& EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] ;
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // NmtRequest does exist
// check if frame is empty and not being filled
if ( pTxBuffer - > m_uiTxMsgLen = =
EPL_DLLK_BUFLEN_EMPTY ) {
// mark Tx buffer as filling is in process
pTxBuffer - >
m_uiTxMsgLen =
EPL_DLLK_BUFLEN_FILLING ;
// set max buffer size as input parameter
uiFrameSize =
pTxBuffer - >
m_uiMaxBufferLen ;
// copy frame from shared loop buffer to Tx buffer
Ret =
EplDllkCalAsyncGetTxFrame
( pTxBuffer - >
m_pbBuffer ,
& uiFrameSize ,
AsyncReqPriority ) ;
if ( Ret = =
kEplSuccessful ) {
pTxFrame =
( tEplFrame
* )
pTxBuffer - >
m_pbBuffer ;
Ret =
EplDllkCheckFrame
( pTxFrame ,
uiFrameSize ) ;
// set buffer valid
pTxBuffer - >
m_uiTxMsgLen
=
uiFrameSize ;
} else if ( Ret = = kEplDllAsyncTxBufferEmpty ) { // empty Tx buffer is not a real problem
// so just ignore it
Ret =
kEplSuccessful ;
// mark Tx buffer as empty
pTxBuffer - >
m_uiTxMsgLen
=
EPL_DLLK_BUFLEN_EMPTY ;
}
}
}
break ;
}
default : // generic priority
{
pTxBuffer =
& EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NONEPL ] ;
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // non-EPL frame does exist
// check if frame is empty and not being filled
if ( pTxBuffer - > m_uiTxMsgLen = =
EPL_DLLK_BUFLEN_EMPTY ) {
// mark Tx buffer as filling is in process
pTxBuffer - >
m_uiTxMsgLen =
EPL_DLLK_BUFLEN_FILLING ;
// set max buffer size as input parameter
uiFrameSize =
pTxBuffer - >
m_uiMaxBufferLen ;
// copy frame from shared loop buffer to Tx buffer
Ret =
EplDllkCalAsyncGetTxFrame
( pTxBuffer - >
m_pbBuffer ,
& uiFrameSize ,
AsyncReqPriority ) ;
if ( Ret = =
kEplSuccessful ) {
pTxFrame =
( tEplFrame
* )
pTxBuffer - >
m_pbBuffer ;
Ret =
EplDllkCheckFrame
( pTxFrame ,
uiFrameSize ) ;
// set buffer valid
pTxBuffer - >
m_uiTxMsgLen
=
uiFrameSize ;
} else if ( Ret = = kEplDllAsyncTxBufferEmpty ) { // empty Tx buffer is not a real problem
// so just ignore it
Ret =
kEplSuccessful ;
// mark Tx buffer as empty
pTxBuffer - >
m_uiTxMsgLen
=
EPL_DLLK_BUFLEN_EMPTY ;
}
}
}
break ;
}
}
NmtState = EplNmtkGetNmtState ( ) ;
if ( ( NmtState = = kEplNmtCsBasicEthernet ) | | ( NmtState = = kEplNmtMsBasicEthernet ) ) { // send frame immediately
if ( pTxFrame ! = NULL ) { // frame is present
// padding is done by Edrv or ethernet controller
Ret = EdrvSendTxMsg ( pTxBuffer ) ;
} else { // no frame moved to TxBuffer
// check if TxBuffers contain unsent frames
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY ) { // NMT request Tx buffer contains a frame
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] ) ;
} else if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NONEPL ] . m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY ) { // non-EPL Tx buffer contains a frame
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NONEPL ] ) ;
}
if ( Ret = = kEplInvalidOperation ) { // ignore error if caused by already active transmission
Ret = kEplSuccessful ;
}
}
// reset PRes flag 2
EplDllkInstance_g . m_bFlag2 = 0 ;
} else {
// update Flag 2 (PR, RS)
Ret =
EplDllkCalAsyncGetTxCount ( & AsyncReqPriority ,
& uiFrameCount ) ;
if ( AsyncReqPriority = = kEplDllAsyncReqPrioNmt ) { // non-empty FIFO with hightest priority is for NMT requests
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY ) { // NMT request Tx buffer contains a frame
// add one more frame
uiFrameCount + + ;
}
} else { // non-empty FIFO with highest priority is for generic frames
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY ) { // NMT request Tx buffer contains a frame
// use NMT request FIFO, because of higher priority
uiFrameCount = 1 ;
AsyncReqPriority =
kEplDllAsyncReqPrioNmt ;
} else if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NONEPL ] . m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY ) { // non-EPL Tx buffer contains a frame
// use NMT request FIFO, because of higher priority
// add one more frame
uiFrameCount + + ;
}
}
if ( uiFrameCount > 7 ) { // limit frame request to send counter to 7
uiFrameCount = 7 ;
}
if ( uiFrameCount > 0 ) {
EplDllkInstance_g . m_bFlag2 =
( BYTE ) ( ( ( AsyncReqPriority < <
EPL_FRAME_FLAG2_PR_SHIFT )
& EPL_FRAME_FLAG2_PR )
| ( uiFrameCount &
EPL_FRAME_FLAG2_RS ) ) ;
} else {
EplDllkInstance_g . m_bFlag2 = 0 ;
}
}
break ;
}
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
case kEplEventTypeDllkStartReducedCycle :
{
// start the reduced cycle by programming the cycle timer
// it is issued by NMT MN module, when PreOp1 is entered
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// clear the asynchronous queues
Ret = EplDllkCalAsyncClearQueues ( ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// reset cycle counter (everytime a SoA is triggerd in PreOp1 the counter is incremented
// and when it reaches EPL_C_DLL_PREOP1_START_CYCLES the SoA may contain invitations)
EplDllkInstance_g . m_uiCycleCount = 0 ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// remove any CN from isochronous phase
while ( EplDllkInstance_g . m_pFirstNodeInfo ! = NULL ) {
EplDllkDeleteNode ( EplDllkInstance_g .
m_pFirstNodeInfo - > m_uiNodeId ) ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// change state to NonCyclic,
// hence EplDllkChangeState() will not ignore the next call
EplDllkInstance_g . m_DllState = kEplDllMsNonCyclic ;
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
if ( EplDllkInstance_g . m_DllConfigParam .
m_dwAsyncSlotTimeout ! = 0 ) {
Ret =
EplTimerHighReskModifyTimerNs
( & EplDllkInstance_g . m_TimerHdlCycle ,
EplDllkInstance_g . m_DllConfigParam .
m_dwAsyncSlotTimeout ,
EplDllkCbMnTimerCycle , 0L , FALSE ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
break ;
}
2008-12-19 20:41:57 +01:00
# endif
# if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
2008-12-20 02:11:52 +01:00
case kEplEventTypeDllkPresReady :
{
// post PRes to transmit FIFO
NmtState = EplNmtkGetNmtState ( ) ;
if ( NmtState ! = kEplNmtCsBasicEthernet ) {
// Does PRes exist?
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] . m_pbBuffer ! = NULL ) { // PRes does exist
pTxFrame =
( tEplFrame * ) EplDllkInstance_g .
m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] .
m_pbBuffer ;
// update frame (NMT state, RD, RS, PR, MS, EN flags)
if ( NmtState < kEplNmtCsPreOperational2 ) { // NMT state is not PreOp2, ReadyToOp or Op
// fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
NmtState =
kEplNmtCsPreOperational2 ;
}
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
if ( NmtState ! = kEplNmtCsOperational ) { // mark PDO as invalid in NMT state Op
// $$$ reset only RD flag; set other flags appropriately
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Pres .
m_le_bFlag1 , 0 ) ;
}
// $$$ make function that updates Pres, StatusRes
// mark PRes frame as ready for transmission
Ret =
EdrvTxMsgReady ( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_PRES ] ) ;
}
}
break ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
default :
{
ASSERTMSG ( FALSE ,
" EplDllkProcess(): unhandled event type! \n " ) ;
}
}
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkConfig
//
// Description: configure parameters of DLL
//
// Parameters: pDllConfigParam_p = configuration parameters
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkConfig ( tEplDllConfigParam * pDllConfigParam_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
// d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
/*tEplNmtState NmtState;
NmtState = EplNmtkGetNmtState ( ) ;
if ( NmtState > kEplNmtGsResetConfiguration )
{ // only allowed in state DLL_GS_INIT
Ret = kEplInvalidOperation ;
goto Exit ;
}
*/
2008-12-20 02:11:52 +01:00
EPL_MEMCPY ( & EplDllkInstance_g . m_DllConfigParam , pDllConfigParam_p ,
( pDllConfigParam_p - > m_uiSizeOfStruct <
sizeof ( tEplDllConfigParam ) ? pDllConfigParam_p - >
m_uiSizeOfStruct : sizeof ( tEplDllConfigParam ) ) ) ;
if ( ( EplDllkInstance_g . m_DllConfigParam . m_dwCycleLen ! = 0 )
& & ( EplDllkInstance_g . m_DllConfigParam . m_dwLossOfFrameTolerance ! = 0 ) ) { // monitor EPL cycle, calculate frame timeout
EplDllkInstance_g . m_ullFrameTimeout = ( 1000LL
*
( ( unsigned long long )
EplDllkInstance_g .
m_DllConfigParam .
m_dwCycleLen ) )
+
( ( unsigned long long ) EplDllkInstance_g . m_DllConfigParam .
m_dwLossOfFrameTolerance ) ;
} else {
EplDllkInstance_g . m_ullFrameTimeout = 0LL ;
}
if ( EplDllkInstance_g . m_DllConfigParam . m_fAsyncOnly ! = FALSE ) { // it is configured as async-only CN
// disable multiplexed cycle, that m_uiCycleCount will not be incremented spuriously on SoC
EplDllkInstance_g . m_DllConfigParam . m_uiMultiplCycleCnt = 0 ;
}
2008-12-19 20:41:57 +01:00
//Exit:
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkSetIdentity
//
// Description: configure identity of local node for IdentResponse
//
// Parameters: pDllIdentParam_p = identity
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkSetIdentity ( tEplDllIdentParam * pDllIdentParam_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
EPL_MEMCPY ( & EplDllkInstance_g . m_DllIdentParam , pDllIdentParam_p ,
( pDllIdentParam_p - > m_uiSizeOfStruct <
sizeof ( tEplDllIdentParam ) ? pDllIdentParam_p - >
m_uiSizeOfStruct : sizeof ( tEplDllIdentParam ) ) ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// $$$ if IdentResponse frame exists update it
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkRegAsyncHandler
//
// Description: registers handler for non-EPL frames
//
// Parameters: pfnDllkCbAsync_p = pointer to callback function
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkRegAsyncHandler ( tEplDllkCbAsync pfnDllkCbAsync_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( EplDllkInstance_g . m_pfnCbAsync = = NULL ) { // no handler registered yet
EplDllkInstance_g . m_pfnCbAsync = pfnDllkCbAsync_p ;
} else { // handler already registered
Ret = kEplDllCbAsyncRegistered ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkDeregAsyncHandler
//
// Description: deregisters handler for non-EPL frames
//
// Parameters: pfnDllkCbAsync_p = pointer to callback function
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkDeregAsyncHandler ( tEplDllkCbAsync pfnDllkCbAsync_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( EplDllkInstance_g . m_pfnCbAsync = = pfnDllkCbAsync_p ) { // same handler is registered
// deregister it
EplDllkInstance_g . m_pfnCbAsync = NULL ;
} else { // wrong handler or no handler registered
Ret = kEplDllCbAsyncRegistered ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkSetAsndServiceIdFilter()
//
// Description: sets the specified node ID filter for the specified
// AsndServiceId. It registers C_DLL_MULTICAST_ASND in ethernet
// driver if any AsndServiceId is open.
//
// Parameters: ServiceId_p = ASnd Service ID
// Filter_p = node ID filter
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
tEplKernel EplDllkSetAsndServiceIdFilter ( tEplDllAsndServiceId ServiceId_p ,
tEplDllAsndFilter Filter_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( ServiceId_p < tabentries ( EplDllkInstance_g . m_aAsndFilter ) ) {
EplDllkInstance_g . m_aAsndFilter [ ServiceId_p ] = Filter_p ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
//---------------------------------------------------------------------------
//
// Function: EplDllkSetFlag1OfNode()
//
// Description: sets Flag1 (for PReq and SoA) of the specified node ID.
//
// Parameters: uiNodeId_p = node ID
// bSoaFlag1_p = flag1
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkSetFlag1OfNode ( unsigned int uiNodeId_p , BYTE bSoaFlag1_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplDllkNodeInfo * pNodeInfo ;
pNodeInfo = EplDllkGetNodeInfo ( uiNodeId_p ) ;
if ( pNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
goto Exit ;
}
// store flag1 in internal node info structure
pNodeInfo - > m_bSoaFlag1 = bSoaFlag1_p ;
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkGetFirstNodeInfo()
//
// Description: returns first info structure of first node in isochronous phase.
// It is only useful for ErrorHandlerk module.
//
// Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
tEplKernel EplDllkGetFirstNodeInfo ( tEplDllkNodeInfo * * ppNodeInfo_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
* ppNodeInfo_p = EplDllkInstance_g . m_pFirstNodeInfo ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkAddNode()
//
// Description: adds the specified node to the isochronous phase.
//
// Parameters: pNodeInfo_p = pointer of node info structure
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkAddNode ( tEplDllNodeInfo * pNodeInfo_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplDllkNodeInfo * pIntNodeInfo ;
tEplDllkNodeInfo * * ppIntNodeInfo ;
unsigned int uiHandle ;
tEplFrame * pFrame ;
unsigned int uiFrameSize ;
pIntNodeInfo = EplDllkGetNodeInfo ( pNodeInfo_p - > m_uiNodeId ) ;
if ( pIntNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
goto Exit ;
}
EPL_DLLK_DBG_POST_TRACE_VALUE ( kEplEventTypeDllkAddNode ,
pNodeInfo_p - > m_uiNodeId , 0 ) ;
// copy node configuration
pIntNodeInfo - > m_dwPresTimeout = pNodeInfo_p - > m_dwPresTimeout ;
pIntNodeInfo - > m_wPresPayloadLimit = pNodeInfo_p - > m_wPresPayloadLimit ;
// $$$ d.k.: actually add node only if MN. On CN it is sufficient to update the node configuration
if ( pNodeInfo_p - > m_uiNodeId = = EplDllkInstance_g . m_DllConfigParam . m_uiNodeId ) { // we shall send PRes ourself
// insert our node at the end of the list
ppIntNodeInfo = & EplDllkInstance_g . m_pFirstNodeInfo ;
while ( ( * ppIntNodeInfo ! = NULL )
& & ( ( * ppIntNodeInfo ) - > m_pNextNodeInfo ! = NULL ) ) {
ppIntNodeInfo = & ( * ppIntNodeInfo ) - > m_pNextNodeInfo ;
}
if ( * ppIntNodeInfo ! = NULL ) {
if ( ( * ppIntNodeInfo ) - > m_uiNodeId = = pNodeInfo_p - > m_uiNodeId ) { // node was already added to list
// $$$ d.k. maybe this should be an error
goto Exit ;
} else { // add our node at the end of the list
ppIntNodeInfo =
& ( * ppIntNodeInfo ) - > m_pNextNodeInfo ;
}
}
// set "PReq"-TxBuffer to PRes-TxBuffer
pIntNodeInfo - > m_pPreqTxBuffer =
& EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ;
} else { // normal CN shall be added to isochronous phase
// insert node into list in ascending order
ppIntNodeInfo = & EplDllkInstance_g . m_pFirstNodeInfo ;
while ( ( * ppIntNodeInfo ! = NULL )
& & ( ( * ppIntNodeInfo ) - > m_uiNodeId <
pNodeInfo_p - > m_uiNodeId )
& & ( ( * ppIntNodeInfo ) - > m_uiNodeId ! =
EplDllkInstance_g . m_DllConfigParam . m_uiNodeId ) ) {
ppIntNodeInfo = & ( * ppIntNodeInfo ) - > m_pNextNodeInfo ;
}
if ( ( * ppIntNodeInfo ! = NULL ) & & ( ( * ppIntNodeInfo ) - > m_uiNodeId = = pNodeInfo_p - > m_uiNodeId ) ) { // node was already added to list
// $$$ d.k. maybe this should be an error
goto Exit ;
}
}
// initialize elements of internal node info structure
pIntNodeInfo - > m_bSoaFlag1 = 0 ;
pIntNodeInfo - > m_fSoftDelete = FALSE ;
pIntNodeInfo - > m_NmtState = kEplNmtCsNotActive ;
if ( pIntNodeInfo - > m_pPreqTxBuffer = = NULL ) { // create TxBuffer entry
uiFrameSize = pNodeInfo_p - > m_wPreqPayloadLimit + 24 ;
Ret =
EplDllkCreateTxFrame ( & uiHandle , & pFrame , & uiFrameSize ,
kEplMsgTypePreq ,
kEplDllAsndNotDefined ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
pIntNodeInfo - > m_pPreqTxBuffer =
& EplDllkInstance_g . m_pTxBuffer [ uiHandle ] ;
AmiSetByteToLe ( & pFrame - > m_le_bDstNodeId ,
( BYTE ) pNodeInfo_p - > m_uiNodeId ) ;
// set up destination MAC address
EPL_MEMCPY ( pFrame - > m_be_abDstMac , pIntNodeInfo - > m_be_abMacAddr ,
6 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
{
tEplFrameInfo FrameInfo ;
// initially encode TPDO -> inform PDO module
FrameInfo . m_pFrame = pFrame ;
FrameInfo . m_uiFrameSize = uiFrameSize ;
Ret = EplPdokCbPdoTransmitted ( & FrameInfo ) ;
}
# endif
}
pIntNodeInfo - > m_ulDllErrorEvents = 0L ;
// add node to list
pIntNodeInfo - > m_pNextNodeInfo = * ppIntNodeInfo ;
* ppIntNodeInfo = pIntNodeInfo ;
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkDeleteNode()
//
// Description: removes the specified node from the isochronous phase.
//
// Parameters: uiNodeId_p = node ID
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkDeleteNode ( unsigned int uiNodeId_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplDllkNodeInfo * pIntNodeInfo ;
tEplDllkNodeInfo * * ppIntNodeInfo ;
unsigned int uiHandle ;
pIntNodeInfo = EplDllkGetNodeInfo ( uiNodeId_p ) ;
if ( pIntNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
goto Exit ;
}
EPL_DLLK_DBG_POST_TRACE_VALUE ( kEplEventTypeDllkDelNode , uiNodeId_p , 0 ) ;
// search node in whole list
ppIntNodeInfo = & EplDllkInstance_g . m_pFirstNodeInfo ;
while ( ( * ppIntNodeInfo ! = NULL )
& & ( ( * ppIntNodeInfo ) - > m_uiNodeId ! = uiNodeId_p ) ) {
ppIntNodeInfo = & ( * ppIntNodeInfo ) - > m_pNextNodeInfo ;
}
if ( ( * ppIntNodeInfo = = NULL ) | | ( ( * ppIntNodeInfo ) - > m_uiNodeId ! = uiNodeId_p ) ) { // node was not found in list
// $$$ d.k. maybe this should be an error
goto Exit ;
}
// remove node from list
* ppIntNodeInfo = pIntNodeInfo - > m_pNextNodeInfo ;
if ( ( pIntNodeInfo - > m_pPreqTxBuffer ! = NULL )
& & ( pIntNodeInfo - > m_pPreqTxBuffer ! = & EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ) ) { // delete TxBuffer entry
uiHandle =
pIntNodeInfo - > m_pPreqTxBuffer -
EplDllkInstance_g . m_pTxBuffer ;
pIntNodeInfo - > m_pPreqTxBuffer = NULL ;
Ret = EplDllkDeleteTxFrame ( uiHandle ) ;
2008-12-19 20:41:57 +01:00
/* if (Ret != kEplSuccessful)
{
goto Exit ;
} */
2008-12-20 02:11:52 +01:00
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkSoftDeleteNode()
//
// Description: removes the specified node not immediately from the isochronous phase.
// Instead the will be removed after error (late/loss PRes) without
// charging the error.
//
// Parameters: uiNodeId_p = node ID
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkSoftDeleteNode ( unsigned int uiNodeId_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplDllkNodeInfo * pIntNodeInfo ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
pIntNodeInfo = EplDllkGetNodeInfo ( uiNodeId_p ) ;
if ( pIntNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
EPL_DLLK_DBG_POST_TRACE_VALUE ( kEplEventTypeDllkSoftDelNode ,
uiNodeId_p , 0 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
pIntNodeInfo - > m_fSoftDelete = TRUE ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
# endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
//=========================================================================//
// //
// P R I V A T E F U N C T I O N S //
// //
//=========================================================================//
//---------------------------------------------------------------------------
//
// Function: EplDllkChangeState
//
// Description: change DLL state on event and diagnose some communication errors
//
// Parameters: NmtEvent_p = DLL event (wrapped in NMT event)
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
static tEplKernel EplDllkChangeState ( tEplNmtEvent NmtEvent_p ,
tEplNmtState NmtState_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplEvent Event ;
tEplErrorHandlerkEvent DllEvent ;
DllEvent . m_ulDllErrorEvents = 0 ;
DllEvent . m_uiNodeId = 0 ;
DllEvent . m_NmtState = NmtState_p ;
switch ( NmtState_p ) {
case kEplNmtGsOff :
case kEplNmtGsInitialising :
case kEplNmtGsResetApplication :
case kEplNmtGsResetCommunication :
case kEplNmtGsResetConfiguration :
case kEplNmtCsBasicEthernet :
// enter DLL_GS_INIT
EplDllkInstance_g . m_DllState = kEplDllGsInit ;
break ;
case kEplNmtCsNotActive :
case kEplNmtCsPreOperational1 :
// reduced EPL cycle is active
if ( NmtEvent_p = = kEplNmtEventDllCeSoc ) { // SoC received
// enter DLL_CS_WAIT_PREQ
EplDllkInstance_g . m_DllState = kEplDllCsWaitPreq ;
} else {
// enter DLL_GS_INIT
EplDllkInstance_g . m_DllState = kEplDllGsInit ;
}
break ;
case kEplNmtCsPreOperational2 :
case kEplNmtCsReadyToOperate :
case kEplNmtCsOperational :
// full EPL cycle is active
switch ( EplDllkInstance_g . m_DllState ) {
case kEplDllCsWaitPreq :
switch ( NmtEvent_p ) {
// DLL_CT2
case kEplNmtEventDllCePreq :
// enter DLL_CS_WAIT_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_RECVD_PREQ ;
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoa ;
break ;
// DLL_CT8
case kEplNmtEventDllCeFrameTimeout :
if ( NmtState_p = = kEplNmtCsPreOperational2 ) { // ignore frame timeout in PreOp2,
// because the previously configured cycle len
// may be wrong.
// 2008/10/15 d.k. If it would not be ignored,
// we would go cyclically to PreOp1 and on next
// SoC back to PreOp2.
break ;
}
// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA |
EPL_DLL_ERR_CN_LOSS_SOC ;
// enter DLL_CS_WAIT_SOC
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoc ;
break ;
case kEplNmtEventDllCeSoa :
// check if multiplexed and PReq should have been received in this cycle
// and if >= NMT_CS_READY_TO_OPERATE
if ( ( EplDllkInstance_g . m_uiCycleCount = = 0 )
& & ( NmtState_p > = kEplNmtCsReadyToOperate ) ) { // report DLL_CEV_LOSS_OF_PREQ
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_PREQ ;
}
// enter DLL_CS_WAIT_SOC
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoc ;
break ;
// DLL_CT7
case kEplNmtEventDllCeSoc :
case kEplNmtEventDllCeAsnd :
// report DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA ;
case kEplNmtEventDllCePres :
default :
// remain in this state
break ;
}
break ;
case kEplDllCsWaitSoc :
switch ( NmtEvent_p ) {
// DLL_CT1
case kEplNmtEventDllCeSoc :
// start of cycle and isochronous phase
// enter DLL_CS_WAIT_PREQ
EplDllkInstance_g . m_DllState =
kEplDllCsWaitPreq ;
break ;
// DLL_CT4
2008-12-19 20:41:57 +01:00
// case kEplNmtEventDllCePres:
2008-12-20 02:11:52 +01:00
case kEplNmtEventDllCeFrameTimeout :
if ( NmtState_p = = kEplNmtCsPreOperational2 ) { // ignore frame timeout in PreOp2,
// because the previously configured cycle len
// may be wrong.
// 2008/10/15 d.k. If it would not be ignored,
// we would go cyclically to PreOp1 and on next
// SoC back to PreOp2.
break ;
}
// fall through
case kEplNmtEventDllCePreq :
case kEplNmtEventDllCeSoa :
// report DLL_CEV_LOSS_SOC
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOC ;
case kEplNmtEventDllCeAsnd :
default :
// remain in this state
break ;
}
break ;
case kEplDllCsWaitSoa :
switch ( NmtEvent_p ) {
case kEplNmtEventDllCeFrameTimeout :
// DLL_CT3
if ( NmtState_p = = kEplNmtCsPreOperational2 ) { // ignore frame timeout in PreOp2,
// because the previously configured cycle len
// may be wrong.
// 2008/10/15 d.k. If it would not be ignored,
// we would go cyclically to PreOp1 and on next
// SoC back to PreOp2.
break ;
}
// fall through
case kEplNmtEventDllCePreq :
// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA |
EPL_DLL_ERR_CN_LOSS_SOC ;
case kEplNmtEventDllCeSoa :
// enter DLL_CS_WAIT_SOC
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoc ;
break ;
// DLL_CT9
case kEplNmtEventDllCeSoc :
// report DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA ;
// enter DLL_CS_WAIT_PREQ
EplDllkInstance_g . m_DllState =
kEplDllCsWaitPreq ;
break ;
// DLL_CT10
case kEplNmtEventDllCeAsnd :
// report DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA ;
case kEplNmtEventDllCePres :
default :
// remain in this state
break ;
}
break ;
case kEplDllGsInit :
// enter DLL_CS_WAIT_PREQ
EplDllkInstance_g . m_DllState = kEplDllCsWaitPreq ;
break ;
default :
break ;
}
break ;
case kEplNmtCsStopped :
// full EPL cycle is active, but without PReq/PRes
switch ( EplDllkInstance_g . m_DllState ) {
case kEplDllCsWaitPreq :
switch ( NmtEvent_p ) {
// DLL_CT2
case kEplNmtEventDllCePreq :
// enter DLL_CS_WAIT_SOA
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoa ;
break ;
// DLL_CT8
case kEplNmtEventDllCeFrameTimeout :
// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA |
EPL_DLL_ERR_CN_LOSS_SOC ;
case kEplNmtEventDllCeSoa :
// NMT_CS_STOPPED active
// it is Ok if no PReq was received
// enter DLL_CS_WAIT_SOC
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoc ;
break ;
// DLL_CT7
case kEplNmtEventDllCeSoc :
case kEplNmtEventDllCeAsnd :
// report DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA ;
case kEplNmtEventDllCePres :
default :
// remain in this state
break ;
}
break ;
case kEplDllCsWaitSoc :
switch ( NmtEvent_p ) {
// DLL_CT1
case kEplNmtEventDllCeSoc :
// start of cycle and isochronous phase
// enter DLL_CS_WAIT_SOA
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoa ;
break ;
// DLL_CT4
2008-12-19 20:41:57 +01:00
// case kEplNmtEventDllCePres:
2008-12-20 02:11:52 +01:00
case kEplNmtEventDllCePreq :
case kEplNmtEventDllCeSoa :
case kEplNmtEventDllCeFrameTimeout :
// report DLL_CEV_LOSS_SOC
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOC ;
case kEplNmtEventDllCeAsnd :
default :
// remain in this state
break ;
}
break ;
case kEplDllCsWaitSoa :
switch ( NmtEvent_p ) {
// DLL_CT3
case kEplNmtEventDllCeFrameTimeout :
// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA |
EPL_DLL_ERR_CN_LOSS_SOC ;
case kEplNmtEventDllCeSoa :
// enter DLL_CS_WAIT_SOC
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoc ;
break ;
// DLL_CT9
case kEplNmtEventDllCeSoc :
// report DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA ;
// remain in DLL_CS_WAIT_SOA
break ;
// DLL_CT10
case kEplNmtEventDllCeAsnd :
// report DLL_CEV_LOSS_SOA
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_CN_LOSS_SOA ;
case kEplNmtEventDllCePreq :
// NMT_CS_STOPPED active and we do not expect any PReq
// so just ignore it
case kEplNmtEventDllCePres :
default :
// remain in this state
break ;
}
break ;
case kEplDllGsInit :
default :
// enter DLL_CS_WAIT_PREQ
EplDllkInstance_g . m_DllState = kEplDllCsWaitSoa ;
break ;
}
break ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
case kEplNmtMsNotActive :
case kEplNmtMsBasicEthernet :
break ;
case kEplNmtMsPreOperational1 :
// reduced EPL cycle is active
if ( EplDllkInstance_g . m_DllState ! = kEplDllMsNonCyclic ) { // stop cycle timer
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret =
EplTimerHighReskDeleteTimer ( & EplDllkInstance_g .
m_TimerHdlCycle ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
EplDllkInstance_g . m_DllState = kEplDllMsNonCyclic ;
// stop further processing,
// because it will be restarted by NMT MN module
break ;
}
switch ( NmtEvent_p ) {
case kEplNmtEventDllMeSocTrig :
case kEplNmtEventDllCeAsnd :
{ // because of reduced EPL cycle SoA shall be triggered, not SoC
tEplDllState DummyDllState ;
Ret =
EplDllkAsyncFrameNotReceived
( EplDllkInstance_g . m_LastReqServiceId ,
EplDllkInstance_g . m_uiLastTargetNodeId ) ;
// go ahead and send SoA
Ret = EplDllkMnSendSoa ( NmtState_p ,
& DummyDllState ,
( EplDllkInstance_g .
m_uiCycleCount > =
EPL_C_DLL_PREOP1_START_CYCLES ) ) ;
// increment cycle counter to detect if EPL_C_DLL_PREOP1_START_CYCLES empty cycles are elapsed
EplDllkInstance_g . m_uiCycleCount + + ;
// reprogram timer
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
if ( EplDllkInstance_g . m_DllConfigParam .
m_dwAsyncSlotTimeout ! = 0 ) {
Ret =
EplTimerHighReskModifyTimerNs
( & EplDllkInstance_g . m_TimerHdlCycle ,
EplDllkInstance_g . m_DllConfigParam .
m_dwAsyncSlotTimeout ,
EplDllkCbMnTimerCycle , 0L , FALSE ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
break ;
}
default :
break ;
}
break ;
case kEplNmtMsPreOperational2 :
case kEplNmtMsReadyToOperate :
case kEplNmtMsOperational :
// full EPL cycle is active
switch ( NmtEvent_p ) {
case kEplNmtEventDllMeSocTrig :
{
// update cycle counter
if ( EplDllkInstance_g . m_DllConfigParam . m_uiMultiplCycleCnt > 0 ) { // multiplexed cycle active
EplDllkInstance_g . m_uiCycleCount =
( EplDllkInstance_g . m_uiCycleCount +
1 ) %
EplDllkInstance_g . m_DllConfigParam .
m_uiMultiplCycleCnt ;
// $$$ check multiplexed cycle restart
// -> toggle MC flag
// -> change node linked list
} else { // non-multiplexed cycle active
// start with first node in isochronous phase
EplDllkInstance_g . m_pCurNodeInfo = NULL ;
}
switch ( EplDllkInstance_g . m_DllState ) {
case kEplDllMsNonCyclic :
{ // start continuous cycle timer
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret =
EplTimerHighReskModifyTimerNs
( & EplDllkInstance_g .
m_TimerHdlCycle ,
EplDllkInstance_g .
m_ullFrameTimeout ,
EplDllkCbMnTimerCycle , 0L ,
TRUE ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// continue with sending SoC
}
case kEplDllMsWaitAsnd :
case kEplDllMsWaitSocTrig :
{ // if m_LastReqServiceId is still valid,
// SoA was not correctly answered
// and user part has to be informed
Ret =
EplDllkAsyncFrameNotReceived
( EplDllkInstance_g .
m_LastReqServiceId ,
EplDllkInstance_g .
m_uiLastTargetNodeId ) ;
// send SoC
Ret = EplDllkMnSendSoc ( ) ;
// new DLL state
EplDllkInstance_g . m_DllState =
kEplDllMsWaitPreqTrig ;
// start WaitSoCPReq Timer
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret =
EplTimerHighReskModifyTimerNs
( & EplDllkInstance_g .
m_TimerHdlResponse ,
EplDllkInstance_g .
m_DllConfigParam .
m_dwWaitSocPreq ,
EplDllkCbMnTimerResponse ,
0L , FALSE ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
break ;
}
default :
{ // wrong DLL state / cycle time exceeded
DllEvent . m_ulDllErrorEvents | =
EPL_DLL_ERR_MN_CYCTIMEEXCEED ;
EplDllkInstance_g . m_DllState =
kEplDllMsWaitSocTrig ;
break ;
}
}
break ;
}
case kEplNmtEventDllMePresTimeout :
{
switch ( EplDllkInstance_g . m_DllState ) {
case kEplDllMsWaitPres :
{ // PRes not received
if ( EplDllkInstance_g . m_pCurNodeInfo - > m_fSoftDelete = = FALSE ) { // normal isochronous CN
DllEvent .
m_ulDllErrorEvents
| =
EPL_DLL_ERR_MN_CN_LOSS_PRES ;
DllEvent . m_uiNodeId =
EplDllkInstance_g .
m_pCurNodeInfo - >
m_uiNodeId ;
} else { // CN shall be deleted softly
Event . m_EventSink =
kEplEventSinkDllkCal ;
Event . m_EventType =
kEplEventTypeDllkSoftDelNode ;
// $$$ d.k. set Event.m_NetTime to current time
Event . m_uiSize =
sizeof ( unsigned
int ) ;
Event . m_pArg =
& EplDllkInstance_g .
m_pCurNodeInfo - >
m_uiNodeId ;
Ret =
EplEventkPost
( & Event ) ;
}
// continue with sending next PReq
}
case kEplDllMsWaitPreqTrig :
{
// send next PReq
Ret =
EplDllkMnSendPreq
( NmtState_p ,
& EplDllkInstance_g .
m_DllState ) ;
break ;
}
default :
{ // wrong DLL state
break ;
}
}
break ;
}
case kEplNmtEventDllCePres :
{
switch ( EplDllkInstance_g . m_DllState ) {
case kEplDllMsWaitPres :
{ // PRes received
// send next PReq
Ret =
EplDllkMnSendPreq
( NmtState_p ,
& EplDllkInstance_g .
m_DllState ) ;
break ;
}
default :
{ // wrong DLL state
break ;
}
}
break ;
}
case kEplNmtEventDllMeSoaTrig :
{
switch ( EplDllkInstance_g . m_DllState ) {
case kEplDllMsWaitSoaTrig :
{ // MN PRes sent
// send SoA
Ret =
EplDllkMnSendSoa ( NmtState_p ,
& EplDllkInstance_g .
m_DllState ,
TRUE ) ;
break ;
}
default :
{ // wrong DLL state
break ;
}
}
break ;
}
case kEplNmtEventDllCeAsnd :
{ // ASnd has been received, but it may be not the requested one
2008-12-19 20:41:57 +01:00
/*
// report if SoA was correctly answered
Ret = EplDllkAsyncFrameNotReceived ( EplDllkInstance_g . m_LastReqServiceId ,
EplDllkInstance_g . m_uiLastTargetNodeId ) ;
*/
2008-12-20 02:11:52 +01:00
if ( EplDllkInstance_g . m_DllState = =
kEplDllMsWaitAsnd ) {
EplDllkInstance_g . m_DllState =
kEplDllMsWaitSocTrig ;
}
break ;
}
default :
break ;
}
break ;
2008-12-19 20:41:57 +01:00
# endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
default :
break ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( DllEvent . m_ulDllErrorEvents ! = 0 ) { // error event set -> post it to error handler
Event . m_EventSink = kEplEventSinkErrk ;
Event . m_EventType = kEplEventTypeDllError ;
// $$$ d.k. set Event.m_NetTime to current time
Event . m_uiSize = sizeof ( DllEvent ) ;
Event . m_pArg = & DllEvent ;
Ret = EplEventkPost ( & Event ) ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCbFrameReceived()
//
// Description: called from EdrvInterruptHandler()
//
// Parameters: pRxBuffer_p = receive buffer structure
//
// Returns: (none)
//
//
// State:
//
//---------------------------------------------------------------------------
static void EplDllkCbFrameReceived ( tEdrvRxBuffer * pRxBuffer_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplNmtState NmtState ;
tEplNmtEvent NmtEvent = kEplNmtEventNoEvent ;
tEplEvent Event ;
tEplFrame * pFrame ;
tEplFrame * pTxFrame ;
tEdrvTxBuffer * pTxBuffer = NULL ;
tEplFrameInfo FrameInfo ;
tEplMsgType MsgType ;
tEplDllReqServiceId ReqServiceId ;
unsigned int uiAsndServiceId ;
unsigned int uiNodeId ;
BYTE bFlag1 ;
BENCHMARK_MOD_02_SET ( 3 ) ;
NmtState = EplNmtkGetNmtState ( ) ;
if ( NmtState < = kEplNmtGsResetConfiguration ) {
goto Exit ;
}
pFrame = ( tEplFrame * ) pRxBuffer_p - > m_pbBuffer ;
2008-12-19 20:41:57 +01:00
# if EDRV_EARLY_RX_INT != FALSE
2008-12-20 02:11:52 +01:00
switch ( pRxBuffer_p - > m_BufferInFrame ) {
case kEdrvBufferFirstInFrame :
{
MsgType =
( tEplMsgType ) AmiGetByteFromLe ( & pFrame - >
m_le_bMessageType ) ;
if ( MsgType = = kEplMsgTypePreq ) {
if ( EplDllkInstance_g . m_DllState = = kEplDllCsWaitPreq ) { // PReq expected and actually received
// d.k.: The condition above is sufficent, because EPL cycle is active
// and no non-EPL frame shall be received in isochronous phase.
// start transmission PRes
// $$$ What if Tx buffer is invalid?
pTxBuffer =
& EplDllkInstance_g .
m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ;
2008-12-19 20:41:57 +01:00
# if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2008-12-20 02:11:52 +01:00
Ret = EdrvTxMsgStart ( pTxBuffer ) ;
2008-12-19 20:41:57 +01:00
# else
2008-12-20 02:11:52 +01:00
pTxFrame =
( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
// update frame (NMT state, RD, RS, PR, MS, EN flags)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
if ( NmtState ! = kEplNmtCsOperational ) { // mark PDO as invalid in NMT state Op
// $$$ reset only RD flag; set other flags appropriately
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Pres .
m_le_bFlag1 , 0 ) ;
}
// $$$ make function that updates Pres, StatusRes
// send PRes frame
Ret = EdrvSendTxMsg ( pTxBuffer ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
}
}
goto Exit ;
}
case kEdrvBufferMiddleInFrame :
{
goto Exit ;
}
case kEdrvBufferLastInFrame :
{
break ;
}
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
FrameInfo . m_pFrame = pFrame ;
FrameInfo . m_uiFrameSize = pRxBuffer_p - > m_uiRxMsgLen ;
FrameInfo . m_NetTime . m_dwNanoSec = pRxBuffer_p - > m_NetTime . m_dwNanoSec ;
FrameInfo . m_NetTime . m_dwSec = pRxBuffer_p - > m_NetTime . m_dwSec ;
if ( AmiGetWordFromBe ( & pFrame - > m_be_wEtherType ) ! = EPL_C_DLL_ETHERTYPE_EPL ) { // non-EPL frame
//TRACE2("EplDllkCbFrameReceived: pfnCbAsync=0x%p SrcMAC=0x%llx\n", EplDllkInstance_g.m_pfnCbAsync, AmiGetQword48FromBe(pFrame->m_be_abSrcMac));
if ( EplDllkInstance_g . m_pfnCbAsync ! = NULL ) { // handler for async frames is registered
EplDllkInstance_g . m_pfnCbAsync ( & FrameInfo ) ;
}
goto Exit ;
}
MsgType = ( tEplMsgType ) AmiGetByteFromLe ( & pFrame - > m_le_bMessageType ) ;
switch ( MsgType ) {
case kEplMsgTypePreq :
{
// PReq frame
// d.k.: (we assume that this PReq frame is intended for us and don't check DstNodeId)
if ( AmiGetByteFromLe ( & pFrame - > m_le_bDstNodeId ) ! = EplDllkInstance_g . m_DllConfigParam . m_uiNodeId ) { // this PReq is not intended for us
goto Exit ;
}
NmtEvent = kEplNmtEventDllCePreq ;
if ( NmtState > = kEplNmtMsNotActive ) { // MN is active -> wrong msg type
break ;
}
2008-12-19 20:41:57 +01:00
# if EDRV_EARLY_RX_INT == FALSE
2008-12-20 02:11:52 +01:00
if ( NmtState > = kEplNmtCsPreOperational2 ) { // respond to and process PReq frames only in PreOp2, ReadyToOp and Op
// Does PRes exist?
pTxBuffer =
& EplDllkInstance_g .
m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ;
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // PRes does exist
2008-12-19 20:41:57 +01:00
# if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2008-12-20 02:11:52 +01:00
EdrvTxMsgStart ( pTxBuffer ) ;
2008-12-19 20:41:57 +01:00
# else
2008-12-20 02:11:52 +01:00
pTxFrame =
( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
// update frame (NMT state, RD, RS, PR, MS, EN flags)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
bFlag1 =
AmiGetByteFromLe ( & pFrame - > m_Data .
m_Preq .
m_le_bFlag1 ) ;
// save EA flag
EplDllkInstance_g . m_bMnFlag1 =
( EplDllkInstance_g .
m_bMnFlag1 & ~ EPL_FRAME_FLAG1_EA )
| ( bFlag1 & EPL_FRAME_FLAG1_EA ) ;
// preserve MS flag
bFlag1 & = EPL_FRAME_FLAG1_MS ;
// add EN flag from Error signaling module
bFlag1 | =
EplDllkInstance_g .
m_bFlag1 & EPL_FRAME_FLAG1_EN ;
if ( NmtState ! = kEplNmtCsOperational ) { // mark PDO as invalid in NMT state Op
// reset only RD flag
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Pres .
m_le_bFlag1 ,
bFlag1 ) ;
} else { // leave RD flag untouched
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Pres .
m_le_bFlag1 ,
( AmiGetByteFromLe
( & pTxFrame - >
m_Data . m_Pres .
m_le_bFlag1 ) &
EPL_FRAME_FLAG1_RD )
| bFlag1 ) ;
}
// $$$ update EPL_DLL_PRES_READY_AFTER_* code
// send PRes frame
Ret = EdrvSendTxMsg ( pTxBuffer ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// inform PDO module
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2008-12-20 02:11:52 +01:00
if ( NmtState > = kEplNmtCsReadyToOperate ) { // inform PDO module only in ReadyToOp and Op
if ( NmtState ! = kEplNmtCsOperational ) {
// reset RD flag and all other flags, but that does not matter, because they were processed above
AmiSetByteToLe ( & pFrame - > m_Data .
m_Preq .
m_le_bFlag1 , 0 ) ;
}
// compares real frame size and PDO size
if ( ( unsigned
int ) ( AmiGetWordFromLe ( & pFrame - >
m_Data .
m_Preq .
m_le_wSize ) +
24 )
> FrameInfo . m_uiFrameSize ) { // format error
tEplErrorHandlerkEvent DllEvent ;
DllEvent . m_ulDllErrorEvents =
EPL_DLL_ERR_INVALID_FORMAT ;
DllEvent . m_uiNodeId =
AmiGetByteFromLe ( & pFrame - >
m_le_bSrcNodeId ) ;
DllEvent . m_NmtState = NmtState ;
Event . m_EventSink =
kEplEventSinkErrk ;
Event . m_EventType =
kEplEventTypeDllError ;
Event . m_NetTime =
FrameInfo . m_NetTime ;
Event . m_uiSize =
sizeof ( DllEvent ) ;
Event . m_pArg = & DllEvent ;
Ret = EplEventkPost ( & Event ) ;
break ;
}
// forward PReq frame as RPDO to PDO module
Ret = EplPdokCbPdoReceived ( & FrameInfo ) ;
}
2008-12-19 20:41:57 +01:00
# if (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2008-12-20 02:11:52 +01:00
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // PRes does exist
// inform PDO module about PRes after PReq
FrameInfo . m_pFrame =
( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
FrameInfo . m_uiFrameSize =
pTxBuffer - > m_uiMaxBufferLen ;
Ret =
EplPdokCbPdoTransmitted ( & FrameInfo ) ;
}
2008-12-19 20:41:57 +01:00
# endif
# endif
# if EDRV_EARLY_RX_INT == FALSE
2008-12-20 02:11:52 +01:00
// $$$ inform emergency protocol handling (error signaling module) about flags
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// reset cycle counter
EplDllkInstance_g . m_uiCycleCount = 0 ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
break ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
case kEplMsgTypePres :
{
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
tEplDllkNodeInfo * pIntNodeInfo ;
tEplHeartbeatEvent HeartbeatEvent ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// PRes frame
NmtEvent = kEplNmtEventDllCePres ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
uiNodeId = AmiGetByteFromLe ( & pFrame - > m_le_bSrcNodeId ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( ( NmtState > = kEplNmtCsPreOperational2 )
& & ( NmtState < = kEplNmtCsOperational ) ) { // process PRes frames only in PreOp2, ReadyToOp and Op of CN
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
pIntNodeInfo = EplDllkGetNodeInfo ( uiNodeId ) ;
if ( pIntNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
goto Exit ;
}
} else if ( EplDllkInstance_g . m_DllState = = kEplDllMsWaitPres ) { // or process PRes frames in MsWaitPres
pIntNodeInfo = EplDllkInstance_g . m_pCurNodeInfo ;
if ( ( pIntNodeInfo = = NULL ) | | ( pIntNodeInfo - > m_uiNodeId ! = uiNodeId ) ) { // ignore PRes, because it is from wrong CN
// $$$ maybe post event to NmtMn module
goto Exit ;
}
// forward Flag2 to asynchronous scheduler
bFlag1 =
AmiGetByteFromLe ( & pFrame - > m_Data . m_Asnd .
m_Payload . m_StatusResponse .
m_le_bFlag2 ) ;
Ret =
EplDllkCalAsyncSetPendingRequests ( uiNodeId ,
( ( tEplDllAsyncReqPriority ) ( ( bFlag1 & EPL_FRAME_FLAG2_PR ) > > EPL_FRAME_FLAG2_PR_SHIFT ) ) , ( bFlag1 & EPL_FRAME_FLAG2_RS ) ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
} else { // ignore PRes, because it was received in wrong NMT state
// but execute EplDllkChangeState() and post event to NMT module
break ;
}
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
{ // check NMT state of CN
HeartbeatEvent . m_wErrorCode = EPL_E_NO_ERROR ;
HeartbeatEvent . m_NmtState =
( tEplNmtState ) ( AmiGetByteFromLe
( & pFrame - > m_Data . m_Pres .
m_le_bNmtStatus ) |
EPL_NMT_TYPE_CS ) ;
if ( pIntNodeInfo - > m_NmtState ! = HeartbeatEvent . m_NmtState ) { // NMT state of CN has changed -> post event to NmtMnu module
if ( pIntNodeInfo - > m_fSoftDelete = = FALSE ) { // normal isochronous CN
HeartbeatEvent . m_uiNodeId =
uiNodeId ;
Event . m_EventSink =
kEplEventSinkNmtMnu ;
Event . m_EventType =
kEplEventTypeHeartbeat ;
Event . m_uiSize =
sizeof ( HeartbeatEvent ) ;
Event . m_pArg = & HeartbeatEvent ;
} else { // CN shall be deleted softly
Event . m_EventSink =
kEplEventSinkDllkCal ;
Event . m_EventType =
kEplEventTypeDllkSoftDelNode ;
Event . m_uiSize =
sizeof ( unsigned int ) ;
Event . m_pArg =
& pIntNodeInfo - > m_uiNodeId ;
}
Event . m_NetTime = FrameInfo . m_NetTime ;
Ret = EplEventkPost ( & Event ) ;
// save current NMT state of CN in internal node structure
pIntNodeInfo - > m_NmtState =
HeartbeatEvent . m_NmtState ;
}
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// inform PDO module
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2008-12-20 02:11:52 +01:00
if ( ( NmtState ! = kEplNmtCsPreOperational2 )
& & ( NmtState ! = kEplNmtMsPreOperational2 ) ) { // inform PDO module only in ReadyToOp and Op
// compare real frame size and PDO size?
if ( ( ( unsigned
int ) ( AmiGetWordFromLe ( & pFrame - > m_Data .
m_Pres . m_le_wSize ) +
24 )
> FrameInfo . m_uiFrameSize )
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
| |
( AmiGetWordFromLe
( & pFrame - > m_Data . m_Pres . m_le_wSize ) >
pIntNodeInfo - > m_wPresPayloadLimit )
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
) { // format error
tEplErrorHandlerkEvent DllEvent ;
DllEvent . m_ulDllErrorEvents =
EPL_DLL_ERR_INVALID_FORMAT ;
DllEvent . m_uiNodeId = uiNodeId ;
DllEvent . m_NmtState = NmtState ;
Event . m_EventSink = kEplEventSinkErrk ;
Event . m_EventType =
kEplEventTypeDllError ;
Event . m_NetTime = FrameInfo . m_NetTime ;
Event . m_uiSize = sizeof ( DllEvent ) ;
Event . m_pArg = & DllEvent ;
Ret = EplEventkPost ( & Event ) ;
break ;
}
if ( ( NmtState ! = kEplNmtCsOperational )
& & ( NmtState ! = kEplNmtMsOperational ) ) {
// reset RD flag and all other flags, but that does not matter, because they were processed above
AmiSetByteToLe ( & pFrame - > m_Data . m_Pres .
m_le_bFlag1 , 0 ) ;
}
Ret = EplPdokCbPdoReceived ( & FrameInfo ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
break ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
case kEplMsgTypeSoc :
{
// SoC frame
NmtEvent = kEplNmtEventDllCeSoc ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( NmtState > = kEplNmtMsNotActive ) { // MN is active -> wrong msg type
break ;
}
2008-12-19 20:41:57 +01:00
# if EPL_DLL_PRES_READY_AFTER_SOC != FALSE
2008-12-20 02:11:52 +01:00
// post PRes to transmit FIFO of the ethernet controller, but don't start
// transmission over bus
pTxBuffer =
& EplDllkInstance_g .
m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ;
// Does PRes exist?
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // PRes does exist
pTxFrame = ( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
// update frame (NMT state, RD, RS, PR, MS, EN flags)
if ( NmtState < kEplNmtCsPreOperational2 ) { // NMT state is not PreOp2, ReadyToOp or Op
// fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
NmtState = kEplNmtCsPreOperational2 ;
}
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bFlag2 ,
EplDllkInstance_g . m_bFlag2 ) ;
if ( NmtState ! = kEplNmtCsOperational ) { // mark PDO as invalid in NMT state Op
// $$$ reset only RD flag; set other flags appropriately
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres .
m_le_bFlag1 , 0 ) ;
}
// $$$ make function that updates Pres, StatusRes
// mark PRes frame as ready for transmission
Ret = EdrvTxMsgReady ( pTxBuffer ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
if ( NmtState > = kEplNmtCsPreOperational2 ) { // SoC frames only in PreOp2, ReadyToOp and Op
// trigger synchronous task
Event . m_EventSink = kEplEventSinkSync ;
Event . m_EventType = kEplEventTypeSync ;
Event . m_uiSize = 0 ;
Ret = EplEventkPost ( & Event ) ;
// update cycle counter
if ( EplDllkInstance_g . m_DllConfigParam . m_uiMultiplCycleCnt > 0 ) { // multiplexed cycle active
EplDllkInstance_g . m_uiCycleCount =
( EplDllkInstance_g . m_uiCycleCount +
1 ) %
EplDllkInstance_g . m_DllConfigParam .
m_uiMultiplCycleCnt ;
}
}
// reprogram timer
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
if ( EplDllkInstance_g . m_ullFrameTimeout ! = 0 ) {
Ret =
EplTimerHighReskModifyTimerNs
( & EplDllkInstance_g . m_TimerHdlCycle ,
EplDllkInstance_g . m_ullFrameTimeout ,
EplDllkCbCnTimer , 0L , FALSE ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
break ;
}
case kEplMsgTypeSoa :
{
// SoA frame
NmtEvent = kEplNmtEventDllCeSoa ;
if ( NmtState > = kEplNmtMsNotActive ) { // MN is active -> wrong msg type
break ;
}
pTxFrame = NULL ;
if ( ( NmtState & EPL_NMT_SUPERSTATE_MASK ) ! = EPL_NMT_CS_EPLMODE ) { // do not respond, if NMT state is < PreOp1 (i.e. not EPL_MODE)
break ;
}
// check TargetNodeId
uiNodeId =
AmiGetByteFromLe ( & pFrame - > m_Data . m_Soa .
m_le_bReqServiceTarget ) ;
if ( uiNodeId = = EplDllkInstance_g . m_DllConfigParam . m_uiNodeId ) { // local node is the target of the current request
// check ServiceId
ReqServiceId =
( tEplDllReqServiceId )
AmiGetByteFromLe ( & pFrame - > m_Data . m_Soa .
m_le_bReqServiceId ) ;
if ( ReqServiceId = = kEplDllReqServiceStatus ) { // StatusRequest
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_STATUSRES ] . m_pbBuffer ! = NULL ) { // StatusRes does exist
pTxFrame =
( tEplFrame * )
EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_STATUSRES ] .
m_pbBuffer ;
// update StatusRes frame (NMT state, EN, EC, RS, PR flags)
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Asnd .
m_Payload .
m_StatusResponse .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Asnd .
m_Payload .
m_StatusResponse .
m_le_bFlag1 ,
EplDllkInstance_g .
m_bFlag1 ) ;
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Asnd .
m_Payload .
m_StatusResponse .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
// send StatusRes
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_STATUSRES ] ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
TGT_DBG_SIGNAL_TRACE_POINT ( 8 ) ;
// update error signaling
bFlag1 =
AmiGetByteFromLe ( & pFrame - >
m_Data .
m_Soa .
m_le_bFlag1 ) ;
if ( ( ( bFlag1 ^ EplDllkInstance_g . m_bMnFlag1 ) & EPL_FRAME_FLAG1_ER ) ! = 0 ) { // exception reset flag was changed by MN
// assume same state for EC in next cycle (clear all other bits)
if ( ( bFlag1 &
EPL_FRAME_FLAG1_ER )
! = 0 ) {
// set EC and reset rest
EplDllkInstance_g .
m_bFlag1 =
EPL_FRAME_FLAG1_EC ;
} else {
// reset complete flag 1 (including EC and EN)
EplDllkInstance_g .
m_bFlag1 =
0 ;
}
}
// save flag 1 from MN for Status request response cycle
EplDllkInstance_g . m_bMnFlag1 =
bFlag1 ;
}
} else if ( ReqServiceId = = kEplDllReqServiceIdent ) { // IdentRequest
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_IDENTRES ] . m_pbBuffer ! = NULL ) { // IdentRes does exist
pTxFrame =
( tEplFrame * )
EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_IDENTRES ] .
m_pbBuffer ;
// update IdentRes frame (NMT state, RS, PR flags)
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Asnd .
m_Payload .
m_IdentResponse .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - >
m_Data . m_Asnd .
m_Payload .
m_IdentResponse .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
// send IdentRes
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_IDENTRES ] ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
TGT_DBG_SIGNAL_TRACE_POINT ( 7 ) ;
}
} else if ( ReqServiceId = = kEplDllReqServiceNmtRequest ) { // NmtRequest
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_pbBuffer ! = NULL ) { // NmtRequest does exist
// check if frame is not empty and not being filled
if ( EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] .
m_uiTxMsgLen >
EPL_DLLK_BUFLEN_FILLING ) {
/*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
{ // pad frame
EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN ;
} */
// memorize transmission
pTxFrame =
( tEplFrame * ) 1 ;
// send NmtRequest
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] ) ;
if ( Ret ! =
kEplSuccessful ) {
goto Exit ;
}
}
}
} else if ( ReqServiceId = = kEplDllReqServiceUnspecified ) { // unspecified invite
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NONEPL ] . m_pbBuffer ! = NULL ) { // non-EPL frame does exist
// check if frame is not empty and not being filled
if ( EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NONEPL ] .
m_uiTxMsgLen >
EPL_DLLK_BUFLEN_FILLING ) {
/*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
{ // pad frame
EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN ;
} */
// memorize transmission
pTxFrame =
( tEplFrame * ) 1 ;
// send non-EPL frame
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NONEPL ] ) ;
if ( Ret ! =
kEplSuccessful ) {
goto Exit ;
}
}
}
} else if ( ReqServiceId = = kEplDllReqServiceNo ) { // no async service requested -> do nothing
}
}
2008-12-19 20:41:57 +01:00
# if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
2008-12-20 02:11:52 +01:00
if ( pTxFrame = = NULL ) { // signal process function readiness of PRes frame
Event . m_EventSink = kEplEventSinkDllk ;
Event . m_EventType = kEplEventTypeDllkPresReady ;
Event . m_uiSize = 0 ;
Event . m_pArg = NULL ;
Ret = EplEventkPost ( & Event ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
// inform PDO module
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
// Ret = EplPdokCbSoa(&FrameInfo);
# endif
2008-12-20 02:11:52 +01:00
// $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// $$$ inform emergency protocol handling about flags
break ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
case kEplMsgTypeAsnd :
{
// ASnd frame
NmtEvent = kEplNmtEventDllCeAsnd ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// ASnd service registered?
uiAsndServiceId =
( unsigned int ) AmiGetByteFromLe ( & pFrame - > m_Data .
m_Asnd .
m_le_bServiceId ) ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
if ( ( EplDllkInstance_g . m_DllState > = kEplDllMsNonCyclic )
& &
( ( ( ( tEplDllAsndServiceId ) uiAsndServiceId ) = =
kEplDllAsndStatusResponse )
| | ( ( ( tEplDllAsndServiceId ) uiAsndServiceId ) = = kEplDllAsndIdentResponse ) ) ) { // StatusRes or IdentRes received
uiNodeId =
AmiGetByteFromLe ( & pFrame - > m_le_bSrcNodeId ) ;
if ( ( EplDllkInstance_g . m_LastReqServiceId = =
( ( tEplDllReqServiceId ) uiAsndServiceId ) )
& & ( uiNodeId = = EplDllkInstance_g . m_uiLastTargetNodeId ) ) { // mark request as responded
EplDllkInstance_g . m_LastReqServiceId =
kEplDllReqServiceNo ;
}
if ( ( ( tEplDllAsndServiceId ) uiAsndServiceId ) = = kEplDllAsndIdentResponse ) { // memorize MAC address of CN for PReq
tEplDllkNodeInfo * pIntNodeInfo ;
pIntNodeInfo =
EplDllkGetNodeInfo ( uiNodeId ) ;
if ( pIntNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
} else {
EPL_MEMCPY ( pIntNodeInfo - >
m_be_abMacAddr ,
pFrame - >
m_be_abSrcMac , 6 ) ;
}
}
// forward Flag2 to asynchronous scheduler
bFlag1 =
AmiGetByteFromLe ( & pFrame - > m_Data . m_Asnd .
m_Payload . m_StatusResponse .
m_le_bFlag2 ) ;
Ret =
EplDllkCalAsyncSetPendingRequests ( uiNodeId ,
( ( tEplDllAsyncReqPriority ) ( ( bFlag1 & EPL_FRAME_FLAG2_PR ) > > EPL_FRAME_FLAG2_PR_SHIFT ) ) , ( bFlag1 & EPL_FRAME_FLAG2_RS ) ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
if ( uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID ) { // ASnd service ID is valid
if ( EplDllkInstance_g . m_aAsndFilter [ uiAsndServiceId ] = = kEplDllAsndFilterAny ) { // ASnd service ID is registered
// forward frame via async receive FIFO to userspace
Ret =
EplDllkCalAsyncFrameReceived
( & FrameInfo ) ;
} else if ( EplDllkInstance_g . m_aAsndFilter [ uiAsndServiceId ] = = kEplDllAsndFilterLocal ) { // ASnd service ID is registered, but only local node ID or broadcasts
// shall be forwarded
uiNodeId =
AmiGetByteFromLe ( & pFrame - >
m_le_bDstNodeId ) ;
if ( ( uiNodeId = =
EplDllkInstance_g . m_DllConfigParam .
m_uiNodeId )
| | ( uiNodeId = = EPL_C_ADR_BROADCAST ) ) { // ASnd frame is intended for us
// forward frame via async receive FIFO to userspace
Ret =
EplDllkCalAsyncFrameReceived
( & FrameInfo ) ;
}
}
}
break ;
}
default :
{
break ;
}
}
if ( NmtEvent ! = kEplNmtEventNoEvent ) { // event for DLL and NMT state machine generated
Ret = EplDllkChangeState ( NmtEvent , NmtState ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
if ( ( NmtEvent ! = kEplNmtEventDllCeAsnd )
& & ( ( NmtState < = kEplNmtCsPreOperational1 ) | | ( NmtEvent ! = kEplNmtEventDllCePres ) ) ) { // NMT state machine is not interested in ASnd frames and PRes frames when not CsNotActive or CsPreOp1
// inform NMT module
Event . m_EventSink = kEplEventSinkNmtk ;
Event . m_EventType = kEplEventTypeNmtEvent ;
Event . m_uiSize = sizeof ( NmtEvent ) ;
Event . m_pArg = & NmtEvent ;
Ret = EplEventkPost ( & Event ) ;
}
}
Exit :
if ( Ret ! = kEplSuccessful ) {
DWORD dwArg ;
BENCHMARK_MOD_02_TOGGLE ( 9 ) ;
dwArg = EplDllkInstance_g . m_DllState | ( NmtEvent < < 8 ) ;
// Error event for API layer
Ret = EplEventkPostError ( kEplEventSourceDllk ,
Ret , sizeof ( dwArg ) , & dwArg ) ;
}
BENCHMARK_MOD_02_RESET ( 3 ) ;
return ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCbFrameTransmitted()
//
// Description: called from EdrvInterruptHandler().
// It signals
//
// Parameters: pRxBuffer_p = receive buffer structure
//
// Returns: (none)
//
//
// State:
//
//---------------------------------------------------------------------------
static void EplDllkCbFrameTransmitted ( tEdrvTxBuffer * pTxBuffer_p )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplEvent Event ;
tEplDllAsyncReqPriority Priority ;
tEplNmtState NmtState ;
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
& & ( EPL_DLL_PRES_READY_AFTER_SOC = = FALSE )
2008-12-20 02:11:52 +01:00
tEplFrameInfo FrameInfo ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
NmtState = EplNmtkGetNmtState ( ) ;
if ( NmtState < = kEplNmtGsResetConfiguration ) {
goto Exit ;
}
if ( ( pTxBuffer_p - EplDllkInstance_g . m_pTxBuffer ) = = EPL_DLLK_TXFRAME_NMTREQ ) { // frame from NMT request FIFO sent
// mark Tx-buffer as empty
pTxBuffer_p - > m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY ;
// post event to DLL
Priority = kEplDllAsyncReqPrioNmt ;
Event . m_EventSink = kEplEventSinkDllk ;
Event . m_EventType = kEplEventTypeDllkFillTx ;
EPL_MEMSET ( & Event . m_NetTime , 0x00 , sizeof ( Event . m_NetTime ) ) ;
Event . m_pArg = & Priority ;
Event . m_uiSize = sizeof ( Priority ) ;
Ret = EplEventkPost ( & Event ) ;
} else if ( ( pTxBuffer_p - EplDllkInstance_g . m_pTxBuffer ) = = EPL_DLLK_TXFRAME_NONEPL ) { // frame from generic priority FIFO sent
// mark Tx-buffer as empty
pTxBuffer_p - > m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY ;
// post event to DLL
Priority = kEplDllAsyncReqPrioGeneric ;
Event . m_EventSink = kEplEventSinkDllk ;
Event . m_EventType = kEplEventTypeDllkFillTx ;
EPL_MEMSET ( & Event . m_NetTime , 0x00 , sizeof ( Event . m_NetTime ) ) ;
Event . m_pArg = & Priority ;
Event . m_uiSize = sizeof ( Priority ) ;
Ret = EplEventkPost ( & Event ) ;
}
2008-12-19 20:41:57 +01:00
# if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
& & ( EPL_DLL_PRES_READY_AFTER_SOC = = FALSE ) ) \
| | ( ( ( EPL_MODULE_INTEGRATION ) & ( EPL_MODULE_NMT_MN ) ) ! = 0 )
2008-12-20 02:11:52 +01:00
else if ( ( pTxBuffer_p - > m_EplMsgType = = kEplMsgTypePreq )
| | ( pTxBuffer_p - > m_EplMsgType = = kEplMsgTypePres ) ) { // PRes resp. PReq frame sent
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
# if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
2008-12-19 20:41:57 +01:00
& & ( EPL_DLL_PRES_READY_AFTER_SOC = = FALSE ) )
2008-12-20 02:11:52 +01:00
{
// inform PDO module
FrameInfo . m_pFrame =
( tEplFrame * ) pTxBuffer_p - > m_pbBuffer ;
FrameInfo . m_uiFrameSize = pTxBuffer_p - > m_uiMaxBufferLen ;
Ret = EplPdokCbPdoTransmitted ( & FrameInfo ) ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
2008-12-19 20:41:57 +01:00
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2008-12-20 02:11:52 +01:00
{
// if own Pres on MN, trigger SoA
if ( ( NmtState > = kEplNmtMsPreOperational2 )
& & ( pTxBuffer_p = =
& EplDllkInstance_g .
m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ) ) {
Ret =
EplDllkChangeState ( kEplNmtEventDllMeSoaTrig ,
NmtState ) ;
}
}
# endif
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
# if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
goto Exit ;
# endif
}
# endif
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
else if ( pTxBuffer_p - > m_EplMsgType = = kEplMsgTypeSoa ) { // SoA frame sent
tEplNmtEvent NmtEvent = kEplNmtEventDllMeSoaSent ;
// check if we are invited
if ( EplDllkInstance_g . m_uiLastTargetNodeId = =
EplDllkInstance_g . m_DllConfigParam . m_uiNodeId ) {
tEplFrame * pTxFrame ;
if ( EplDllkInstance_g . m_LastReqServiceId = = kEplDllReqServiceStatus ) { // StatusRequest
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_STATUSRES ] . m_pbBuffer ! = NULL ) { // StatusRes does exist
pTxFrame =
( tEplFrame * ) EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_STATUSRES ] .
m_pbBuffer ;
// update StatusRes frame (NMT state, EN, EC, RS, PR flags)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd .
m_Payload .
m_StatusResponse .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd .
m_Payload .
m_StatusResponse .
m_le_bFlag1 ,
EplDllkInstance_g .
m_bFlag1 ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd .
m_Payload .
m_StatusResponse .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
// send StatusRes
Ret =
EdrvSendTxMsg ( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_STATUSRES ] ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
TGT_DBG_SIGNAL_TRACE_POINT ( 8 ) ;
}
} else if ( EplDllkInstance_g . m_LastReqServiceId = = kEplDllReqServiceIdent ) { // IdentRequest
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_IDENTRES ] . m_pbBuffer ! = NULL ) { // IdentRes does exist
pTxFrame =
( tEplFrame * ) EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_IDENTRES ] .
m_pbBuffer ;
// update IdentRes frame (NMT state, RS, PR flags)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd .
m_Payload .
m_IdentResponse .
m_le_bNmtStatus ,
( BYTE ) NmtState ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Asnd .
m_Payload .
m_IdentResponse .
m_le_bFlag2 ,
EplDllkInstance_g .
m_bFlag2 ) ;
// send IdentRes
Ret =
EdrvSendTxMsg ( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_IDENTRES ] ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
TGT_DBG_SIGNAL_TRACE_POINT ( 7 ) ;
}
} else if ( EplDllkInstance_g . m_LastReqServiceId = = kEplDllReqServiceNmtRequest ) { // NmtRequest
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NMTREQ ] . m_pbBuffer ! = NULL ) { // NmtRequest does exist
// check if frame is not empty and not being filled
if ( EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] .
m_uiTxMsgLen >
EPL_DLLK_BUFLEN_FILLING ) {
// check if this frame is a NMT command,
// then forward this frame back to NmtMnu module,
// because it needs the time, when this frame is
// actually sent, to start the timer for monitoring
// the NMT state change.
pTxFrame =
( tEplFrame * )
EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] .
m_pbBuffer ;
if ( ( AmiGetByteFromLe
( & pTxFrame - >
m_le_bMessageType )
= = ( BYTE ) kEplMsgTypeAsnd )
& &
( AmiGetByteFromLe
( & pTxFrame - > m_Data . m_Asnd .
m_le_bServiceId )
= = ( BYTE ) kEplDllAsndNmtCommand ) ) { // post event directly to NmtMnu module
Event . m_EventSink =
kEplEventSinkNmtMnu ;
Event . m_EventType =
kEplEventTypeNmtMnuNmtCmdSent ;
Event . m_uiSize =
EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] .
m_uiTxMsgLen ;
Event . m_pArg = pTxFrame ;
Ret =
EplEventkPost
( & Event ) ;
}
// send NmtRequest
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NMTREQ ] ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
}
}
} else if ( EplDllkInstance_g . m_LastReqServiceId = = kEplDllReqServiceUnspecified ) { // unspecified invite
if ( EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_NONEPL ] . m_pbBuffer ! = NULL ) { // non-EPL frame does exist
// check if frame is not empty and not being filled
if ( EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NONEPL ] .
m_uiTxMsgLen >
EPL_DLLK_BUFLEN_FILLING ) {
// send non-EPL frame
Ret =
EdrvSendTxMsg
( & EplDllkInstance_g .
m_pTxBuffer
[ EPL_DLLK_TXFRAME_NONEPL ] ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
}
}
}
// ASnd frame was sent, remove the request
EplDllkInstance_g . m_LastReqServiceId =
kEplDllReqServiceNo ;
}
// forward event to ErrorHandler and PDO module
Event . m_EventSink = kEplEventSinkNmtk ;
Event . m_EventType = kEplEventTypeNmtEvent ;
Event . m_uiSize = sizeof ( NmtEvent ) ;
Event . m_pArg = & NmtEvent ;
Ret = EplEventkPost ( & Event ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
}
2008-12-19 20:41:57 +01:00
# endif
# if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
2008-12-20 02:11:52 +01:00
else { // d.k.: Why that else? on CN it is entered on IdentRes and StatusRes
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// signal process function readiness of PRes frame
Event . m_EventSink = kEplEventSinkDllk ;
Event . m_EventType = kEplEventTypeDllkPresReady ;
Event . m_uiSize = 0 ;
Event . m_pArg = NULL ;
Ret = EplEventkPost ( & Event ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
Exit :
if ( Ret ! = kEplSuccessful ) {
DWORD dwArg ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
BENCHMARK_MOD_02_TOGGLE ( 9 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
dwArg =
EplDllkInstance_g . m_DllState | ( pTxBuffer_p - >
m_EplMsgType < < 16 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// Error event for API layer
Ret = EplEventkPostError ( kEplEventSourceDllk ,
Ret , sizeof ( dwArg ) , & dwArg ) ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCheckFrame()
//
// Description: check frame and set missing information
//
// Parameters: pFrame_p = ethernet frame
// uiFrameSize_p = size of frame
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
static tEplKernel EplDllkCheckFrame ( tEplFrame * pFrame_p ,
unsigned int uiFrameSize_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplMsgType MsgType ;
WORD wEtherType ;
// check frame
if ( pFrame_p ! = NULL ) {
// check SrcMAC
if ( AmiGetQword48FromBe ( pFrame_p - > m_be_abSrcMac ) = = 0 ) {
// source MAC address
EPL_MEMCPY ( & pFrame_p - > m_be_abSrcMac [ 0 ] ,
& EplDllkInstance_g . m_be_abSrcMac [ 0 ] , 6 ) ;
}
// check ethertype
wEtherType = AmiGetWordFromBe ( & pFrame_p - > m_be_wEtherType ) ;
if ( wEtherType = = 0 ) {
// assume EPL frame
wEtherType = EPL_C_DLL_ETHERTYPE_EPL ;
AmiSetWordToBe ( & pFrame_p - > m_be_wEtherType , wEtherType ) ;
}
if ( wEtherType = = EPL_C_DLL_ETHERTYPE_EPL ) {
// source node ID
AmiSetByteToLe ( & pFrame_p - > m_le_bSrcNodeId ,
( BYTE ) EplDllkInstance_g .
m_DllConfigParam . m_uiNodeId ) ;
// check message type
MsgType =
AmiGetByteFromLe ( & pFrame_p - > m_le_bMessageType ) ;
if ( MsgType = = 0 ) {
MsgType = kEplMsgTypeAsnd ;
AmiSetByteToLe ( & pFrame_p - > m_le_bMessageType ,
( BYTE ) MsgType ) ;
}
if ( MsgType = = kEplMsgTypeAsnd ) {
// destination MAC address
AmiSetQword48ToBe ( & pFrame_p - > m_be_abDstMac [ 0 ] ,
EPL_C_DLL_MULTICAST_ASND ) ;
}
}
}
return kEplSuccessful ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCbCnTimer()
//
// Description: called by timer module. It monitors the EPL cycle when it is a CN.
//
// Parameters: pEventArg_p = timer event argument
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
static tEplKernel PUBLIC EplDllkCbCnTimer ( tEplTimerEventArg * pEventArg_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplNmtState NmtState ;
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
if ( pEventArg_p - > m_TimerHdl ! = EplDllkInstance_g . m_TimerHdlCycle ) { // zombie callback
// just exit
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
NmtState = EplNmtkGetNmtState ( ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( NmtState < = kEplNmtGsResetConfiguration ) {
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Ret = EplDllkChangeState ( kEplNmtEventDllCeFrameTimeout , NmtState ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
// 2008/10/15 d.k. reprogramming of timer not necessary,
// because it will be programmed, when SoC is received.
2008-12-19 20:41:57 +01:00
/*
// reprogram timer
# if EPL_TIMER_USE_HIGHRES != FALSE
if ( ( NmtState > kEplNmtCsPreOperational1 )
& & ( EplDllkInstance_g . m_ullFrameTimeout ! = 0 ) )
{
Ret = EplTimerHighReskModifyTimerNs ( & EplDllkInstance_g . m_TimerHdlCycle , EplDllkInstance_g . m_ullFrameTimeout , EplDllkCbCnTimer , 0L , FALSE ) ;
}
# endif
*/
2008-12-20 02:11:52 +01:00
Exit :
if ( Ret ! = kEplSuccessful ) {
DWORD dwArg ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
BENCHMARK_MOD_02_TOGGLE ( 9 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
dwArg =
EplDllkInstance_g .
m_DllState | ( kEplNmtEventDllCeFrameTimeout < < 8 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// Error event for API layer
Ret = EplEventkPostError ( kEplEventSourceDllk ,
Ret , sizeof ( dwArg ) , & dwArg ) ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
# endif
# if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
//---------------------------------------------------------------------------
//
// Function: EplDllkCbMnTimerCycle()
//
// Description: called by timer module. It triggers the SoC when it is a MN.
//
// Parameters: pEventArg_p = timer event argument
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
static tEplKernel PUBLIC EplDllkCbMnTimerCycle ( tEplTimerEventArg * pEventArg_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplNmtState NmtState ;
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
if ( pEventArg_p - > m_TimerHdl ! = EplDllkInstance_g . m_TimerHdlCycle ) { // zombie callback
// just exit
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
NmtState = EplNmtkGetNmtState ( ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( NmtState < = kEplNmtGsResetConfiguration ) {
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Ret = EplDllkChangeState ( kEplNmtEventDllMeSocTrig , NmtState ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Exit :
if ( Ret ! = kEplSuccessful ) {
DWORD dwArg ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
BENCHMARK_MOD_02_TOGGLE ( 9 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
dwArg =
EplDllkInstance_g .
m_DllState | ( kEplNmtEventDllMeSocTrig < < 8 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// Error event for API layer
Ret = EplEventkPostError ( kEplEventSourceDllk ,
Ret , sizeof ( dwArg ) , & dwArg ) ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCbMnTimerResponse()
//
// Description: called by timer module. It monitors the PRes timeout.
//
// Parameters: pEventArg_p = timer event argument
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
static tEplKernel PUBLIC EplDllkCbMnTimerResponse ( tEplTimerEventArg *
pEventArg_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEplNmtState NmtState ;
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
if ( pEventArg_p - > m_TimerHdl ! = EplDllkInstance_g . m_TimerHdlResponse ) { // zombie callback
// just exit
goto Exit ;
}
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
NmtState = EplNmtkGetNmtState ( ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
if ( NmtState < = kEplNmtGsResetConfiguration ) {
goto Exit ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Ret = EplDllkChangeState ( kEplNmtEventDllMePresTimeout , NmtState ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
Exit :
if ( Ret ! = kEplSuccessful ) {
DWORD dwArg ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
BENCHMARK_MOD_02_TOGGLE ( 9 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
dwArg =
EplDllkInstance_g .
m_DllState | ( kEplNmtEventDllMePresTimeout < < 8 ) ;
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
// Error event for API layer
Ret = EplEventkPostError ( kEplEventSourceDllk ,
Ret , sizeof ( dwArg ) , & dwArg ) ;
}
2008-12-19 20:41:57 +01:00
2008-12-20 02:11:52 +01:00
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkGetNodeInfo()
//
// Description: returns node info structure of the specified node.
//
// Parameters: uiNodeId_p = node ID
//
// Returns: tEplDllkNodeInfo* = pointer to internal node info structure
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
static tEplDllkNodeInfo * EplDllkGetNodeInfo ( unsigned int uiNodeId_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
// $$$ d.k.: use hash algorithm to retrieve the appropriate node info structure
// if size of array is less than 254.
uiNodeId_p - - ; // node ID starts at 1 but array at 0
if ( uiNodeId_p > = tabentries ( EplDllkInstance_g . m_aNodeInfo ) ) {
return NULL ;
} else {
return & EplDllkInstance_g . m_aNodeInfo [ uiNodeId_p ] ;
}
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkMnSendSoa()
//
// Description: it updates and transmits the SoA.
//
// Parameters: NmtState_p = current NMT state
// pDllStateProposed_p = proposed DLL state
// fEnableInvitation_p = enable invitation for asynchronous phase
// it will be disabled for EPL_C_DLL_PREOP1_START_CYCLES SoAs
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
static tEplKernel EplDllkMnSendSoa ( tEplNmtState NmtState_p ,
2008-12-20 02:11:52 +01:00
tEplDllState * pDllStateProposed_p ,
BOOL fEnableInvitation_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEdrvTxBuffer * pTxBuffer = NULL ;
tEplFrame * pTxFrame ;
tEplDllkNodeInfo * pNodeInfo ;
* pDllStateProposed_p = kEplDllMsNonCyclic ;
pTxBuffer = & EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_SOA ] ;
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // SoA does exist
pTxFrame = ( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
if ( fEnableInvitation_p ! = FALSE ) { // fetch target of asynchronous phase
if ( EplDllkInstance_g . m_bFlag2 = = 0 ) { // own queues are empty
EplDllkInstance_g . m_LastReqServiceId =
kEplDllReqServiceNo ;
} else if ( ( ( tEplDllAsyncReqPriority ) ( EplDllkInstance_g . m_bFlag2 > > EPL_FRAME_FLAG2_PR_SHIFT ) ) = = kEplDllAsyncReqPrioNmt ) { // frames in own NMT request queue available
EplDllkInstance_g . m_LastReqServiceId =
kEplDllReqServiceNmtRequest ;
} else {
EplDllkInstance_g . m_LastReqServiceId =
kEplDllReqServiceUnspecified ;
}
Ret =
EplDllkCalAsyncGetSoaRequest ( & EplDllkInstance_g .
m_LastReqServiceId ,
& EplDllkInstance_g .
m_uiLastTargetNodeId ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
if ( EplDllkInstance_g . m_LastReqServiceId ! = kEplDllReqServiceNo ) { // asynchronous phase will be assigned to one node
if ( EplDllkInstance_g . m_uiLastTargetNodeId = = EPL_C_ADR_INVALID ) { // exchange invalid node ID with local node ID
EplDllkInstance_g . m_uiLastTargetNodeId =
EplDllkInstance_g . m_DllConfigParam .
m_uiNodeId ;
// d.k. DLL state WaitAsndTrig is not helpful;
// so just step over to WaitSocTrig,
// because own ASnd is sent automatically in CbFrameTransmitted() after SoA.
//*pDllStateProposed_p = kEplDllMsWaitAsndTrig;
* pDllStateProposed_p =
kEplDllMsWaitSocTrig ;
} else { // assignment to CN
* pDllStateProposed_p =
kEplDllMsWaitAsnd ;
}
pNodeInfo =
EplDllkGetNodeInfo ( EplDllkInstance_g .
m_uiLastTargetNodeId ) ;
if ( pNodeInfo = = NULL ) { // no node info structure available
Ret = kEplDllNoNodeInfo ;
goto Exit ;
}
// update frame (EA, ER flags)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa .
m_le_bFlag1 ,
pNodeInfo - >
m_bSoaFlag1 & ( EPL_FRAME_FLAG1_EA
|
EPL_FRAME_FLAG1_ER ) ) ;
} else { // no assignment of asynchronous phase
* pDllStateProposed_p = kEplDllMsWaitSocTrig ;
EplDllkInstance_g . m_uiLastTargetNodeId =
EPL_C_ADR_INVALID ;
}
// update frame (target)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa .
m_le_bReqServiceId ,
( BYTE ) EplDllkInstance_g .
m_LastReqServiceId ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa .
m_le_bReqServiceTarget ,
( BYTE ) EplDllkInstance_g .
m_uiLastTargetNodeId ) ;
} else { // invite nobody
// update frame (target)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa .
m_le_bReqServiceId , ( BYTE ) 0 ) ;
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa .
m_le_bReqServiceTarget , ( BYTE ) 0 ) ;
}
// update frame (NMT state)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Soa . m_le_bNmtStatus ,
( BYTE ) NmtState_p ) ;
// send SoA frame
Ret = EdrvSendTxMsg ( pTxBuffer ) ;
}
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkMnSendSoc()
//
// Description: it updates and transmits the SoA.
//
// Parameters: (none)
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
static tEplKernel EplDllkMnSendSoc ( void )
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEdrvTxBuffer * pTxBuffer = NULL ;
tEplFrame * pTxFrame ;
tEplEvent Event ;
pTxBuffer = & EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_SOC ] ;
if ( pTxBuffer - > m_pbBuffer ! = NULL ) { // SoC does exist
pTxFrame = ( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
// $$$ update NetTime
// send SoC frame
Ret = EdrvSendTxMsg ( pTxBuffer ) ;
if ( Ret ! = kEplSuccessful ) {
goto Exit ;
}
// trigger synchronous task
Event . m_EventSink = kEplEventSinkSync ;
Event . m_EventType = kEplEventTypeSync ;
Event . m_uiSize = 0 ;
Ret = EplEventkPost ( & Event ) ;
}
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkMnSendPreq()
//
// Description: it updates and transmits the PReq for the next isochronous CN
// or own PRes if enabled.
//
// Parameters: NmtState_p = current NMT state
// pDllStateProposed_p = proposed DLL state
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
static tEplKernel EplDllkMnSendPreq ( tEplNmtState NmtState_p ,
2008-12-20 02:11:52 +01:00
tEplDllState * pDllStateProposed_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
tEdrvTxBuffer * pTxBuffer = NULL ;
tEplFrame * pTxFrame ;
BYTE bFlag1 = 0 ;
if ( EplDllkInstance_g . m_pCurNodeInfo = = NULL ) { // start with first isochronous CN
EplDllkInstance_g . m_pCurNodeInfo =
EplDllkInstance_g . m_pFirstNodeInfo ;
} else { // iterate to next isochronous CN
EplDllkInstance_g . m_pCurNodeInfo =
EplDllkInstance_g . m_pCurNodeInfo - > m_pNextNodeInfo ;
}
if ( EplDllkInstance_g . m_pCurNodeInfo = = NULL ) { // last isochronous CN reached
Ret = EplDllkMnSendSoa ( NmtState_p , pDllStateProposed_p , TRUE ) ;
goto Exit ;
} else {
pTxBuffer = EplDllkInstance_g . m_pCurNodeInfo - > m_pPreqTxBuffer ;
bFlag1 =
EplDllkInstance_g . m_pCurNodeInfo - >
m_bSoaFlag1 & EPL_FRAME_FLAG1_EA ;
* pDllStateProposed_p = kEplDllMsWaitPres ;
// start PRes Timer
// $$$ d.k.: maybe move this call to CbFrameTransmitted(), because the time should run from there
2008-12-19 20:41:57 +01:00
# if EPL_TIMER_USE_HIGHRES != FALSE
2008-12-20 02:11:52 +01:00
Ret =
EplTimerHighReskModifyTimerNs ( & EplDllkInstance_g .
m_TimerHdlResponse ,
EplDllkInstance_g .
m_pCurNodeInfo - >
m_dwPresTimeout ,
EplDllkCbMnTimerResponse , 0L ,
FALSE ) ;
2008-12-19 20:41:57 +01:00
# endif
2008-12-20 02:11:52 +01:00
}
if ( pTxBuffer = = NULL ) { // PReq does not exist
Ret = kEplDllTxBufNotReady ;
goto Exit ;
}
pTxFrame = ( tEplFrame * ) pTxBuffer - > m_pbBuffer ;
if ( pTxFrame ! = NULL ) { // PReq does exist
if ( NmtState_p = = kEplNmtMsOperational ) { // leave RD flag untouched
bFlag1 | =
AmiGetByteFromLe ( & pTxFrame - > m_Data . m_Preq .
m_le_bFlag1 ) & EPL_FRAME_FLAG1_RD ;
}
if ( pTxBuffer = = & EplDllkInstance_g . m_pTxBuffer [ EPL_DLLK_TXFRAME_PRES ] ) { // PRes of MN will be sent
// update NMT state
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Pres . m_le_bNmtStatus ,
( BYTE ) NmtState_p ) ;
* pDllStateProposed_p = kEplDllMsWaitSoaTrig ;
}
// $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary
// update frame (Flag1)
AmiSetByteToLe ( & pTxFrame - > m_Data . m_Preq . m_le_bFlag1 , bFlag1 ) ;
// calculate frame size from payload size
pTxBuffer - > m_uiTxMsgLen =
AmiGetWordFromLe ( & pTxFrame - > m_Data . m_Preq . m_le_wSize ) + 24 ;
// send PReq frame
Ret = EdrvSendTxMsg ( pTxBuffer ) ;
} else {
Ret = kEplDllTxFrameInvalid ;
}
Exit :
return Ret ;
2008-12-19 20:41:57 +01:00
}
//---------------------------------------------------------------------------
//
// Function: EplDllkAsyncFrameNotReceived()
//
// Description: passes empty ASnd frame to receive FIFO.
// It will be called only for frames with registered AsndServiceIds
// (only kEplDllAsndFilterAny).
//
// Parameters: none
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
2008-12-20 02:11:52 +01:00
static tEplKernel EplDllkAsyncFrameNotReceived ( tEplDllReqServiceId
ReqServiceId_p ,
unsigned int uiNodeId_p )
2008-12-19 20:41:57 +01:00
{
2008-12-20 02:11:52 +01:00
tEplKernel Ret = kEplSuccessful ;
BYTE abBuffer [ 18 ] ;
tEplFrame * pFrame = ( tEplFrame * ) abBuffer ;
tEplFrameInfo FrameInfo ;
// check if previous SoA invitation was not answered
switch ( ReqServiceId_p ) {
case kEplDllReqServiceIdent :
case kEplDllReqServiceStatus :
// ASnd service registered?
if ( EplDllkInstance_g . m_aAsndFilter [ ReqServiceId_p ] = = kEplDllAsndFilterAny ) { // ASnd service ID is registered
AmiSetByteToLe ( & pFrame - > m_le_bSrcNodeId ,
( BYTE ) uiNodeId_p ) ;
// EPL MsgType ASnd
AmiSetByteToLe ( & pFrame - > m_le_bMessageType ,
( BYTE ) kEplMsgTypeAsnd ) ;
// ASnd Service ID
AmiSetByteToLe ( & pFrame - > m_Data . m_Asnd . m_le_bServiceId ,
( BYTE ) ReqServiceId_p ) ;
// create frame info structure
FrameInfo . m_pFrame = pFrame ;
FrameInfo . m_uiFrameSize = 18 ; // empty non existing ASnd frame
// forward frame via async receive FIFO to userspace
Ret = EplDllkCalAsyncFrameReceived ( & FrameInfo ) ;
}
break ;
default :
// no invitation issued or it was successfully answered or it is uninteresting
break ;
}
return Ret ;
2008-12-19 20:41:57 +01:00
}
# endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
# endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
// EOF