blob: 0e283d5d018157446ec1d77be296dbf2a1883b19 [file] [log] [blame]
/****************************************************************************
(c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
www.systec-electronic.com
Project: openPOWERLINK
Description: source file for kernel DLL Communication Abstraction Layer 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: EplDllkCal.c,v $
$Author: D.Krueger $
$Revision: 1.7 $ $Date: 2008/11/13 17:13:09 $
$State: Exp $
Build Environment:
GCC V3.4
-------------------------------------------------------------------------
Revision History:
2006/06/15 d.k.: start of the implementation, version 1.00
****************************************************************************/
#include "kernel/EplDllkCal.h"
#include "kernel/EplDllk.h"
#include "kernel/EplEventk.h"
#include "EplDllCal.h"
#ifndef EPL_NO_FIFO
#include "SharedBuff.h"
#endif
#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
/***************************************************************************/
/* */
/* */
/* G L O B A L D E F I N I T I O N S */
/* */
/* */
/***************************************************************************/
//---------------------------------------------------------------------------
// const defines
//---------------------------------------------------------------------------
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
//---------------------------------------------------------------------------
// local types
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// modul globale vars
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// local function prototypes
//---------------------------------------------------------------------------
/***************************************************************************/
/* */
/* */
/* C L A S S EplDllkCal */
/* */
/* */
/***************************************************************************/
//
// Description:
//
//
/***************************************************************************/
//=========================================================================//
// //
// P R I V A T E D E F I N I T I O N S //
// //
//=========================================================================//
//---------------------------------------------------------------------------
// const defines
//---------------------------------------------------------------------------
#define EPL_DLLKCAL_MAX_QUEUES 5 // CnGenReq, CnNmtReq, {MnGenReq, MnNmtReq}, MnIdentReq, MnStatusReq
//---------------------------------------------------------------------------
// local types
//---------------------------------------------------------------------------
typedef struct {
#ifndef EPL_NO_FIFO
// tShbInstance m_ShbInstanceRx; // FIFO for Rx ASnd frames
tShbInstance m_ShbInstanceTxNmt; // FIFO for Tx frames with NMT request priority
tShbInstance m_ShbInstanceTxGen; // FIFO for Tx frames with generic priority
#else
unsigned int m_uiFrameSizeNmt;
u8 m_abFrameNmt[1500];
unsigned int m_uiFrameSizeGen;
u8 m_abFrameGen[1500];
#endif
tEplDllkCalStatistics m_Statistics;
#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
// IdentRequest queue with CN node IDs
unsigned int m_auiQueueIdentReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty
unsigned int m_uiWriteIdentReq;
unsigned int m_uiReadIdentReq;
// StatusRequest queue with CN node IDs
unsigned int m_auiQueueStatusReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty
unsigned int m_uiWriteStatusReq;
unsigned int m_uiReadStatusReq;
unsigned int m_auiQueueCnRequests[254 * 2];
// first 254 entries represent the generic requests of the corresponding node
// second 254 entries represent the NMT requests of the corresponding node
unsigned int m_uiNextQueueCnRequest;
unsigned int m_uiNextRequestQueue;
#endif
} tEplDllkCalInstance;
//---------------------------------------------------------------------------
// local vars
//---------------------------------------------------------------------------
// if no dynamic memory allocation shall be used
// define structures statically
static tEplDllkCalInstance EplDllkCalInstance_g;
//---------------------------------------------------------------------------
// local function prototypes
//---------------------------------------------------------------------------
//=========================================================================//
// //
// P U B L I C F U N C T I O N S //
// //
//=========================================================================//
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAddInstance()
//
// Description: add and initialize new instance of DLL CAL module
//
// Parameters: none
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAddInstance(void)
{
tEplKernel Ret = kEplSuccessful;
#ifndef EPL_NO_FIFO
tShbError ShbError;
unsigned int fShbNewCreated;
/* ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_RX, EPL_DLLCAL_BUFFER_ID_RX,
&EplDllkCalInstance_g.m_ShbInstanceRx, &fShbNewCreated);
// returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
if (ShbError != kShbOk)
{
Ret = kEplNoResource;
}
*/
ShbError =
ShbCirAllocBuffer(EPL_DLLCAL_BUFFER_SIZE_TX_NMT,
EPL_DLLCAL_BUFFER_ID_TX_NMT,
&EplDllkCalInstance_g.m_ShbInstanceTxNmt,
&fShbNewCreated);
// returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
if (ShbError != kShbOk) {
Ret = kEplNoResource;
}
/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxNmt, EplDllkCalTxNmtSignalHandler, kShbPriorityNormal);
// returns kShbOk, kShbAlreadySignaling or kShbInvalidArg
if (ShbError != kShbOk)
{
Ret = kEplNoResource;
}
*/
ShbError =
ShbCirAllocBuffer(EPL_DLLCAL_BUFFER_SIZE_TX_GEN,
EPL_DLLCAL_BUFFER_ID_TX_GEN,
&EplDllkCalInstance_g.m_ShbInstanceTxGen,
&fShbNewCreated);
// returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
if (ShbError != kShbOk) {
Ret = kEplNoResource;
}
/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxGen, EplDllkCalTxGenSignalHandler, kShbPriorityNormal);
// returns kShbOk, kShbAlreadySignaling or kShbInvalidArg
if (ShbError != kShbOk)
{
Ret = kEplNoResource;
}
*/
#else
EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
#endif
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalDelInstance()
//
// Description: deletes instance of DLL CAL module
//
// Parameters: none
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalDelInstance(void)
{
tEplKernel Ret = kEplSuccessful;
#ifndef EPL_NO_FIFO
tShbError ShbError;
/* ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceRx);
if (ShbError != kShbOk)
{
Ret = kEplNoResource;
}
EplDllkCalInstance_g.m_ShbInstanceRx = NULL;
*/
ShbError = ShbCirReleaseBuffer(EplDllkCalInstance_g.m_ShbInstanceTxNmt);
if (ShbError != kShbOk) {
Ret = kEplNoResource;
}
EplDllkCalInstance_g.m_ShbInstanceTxNmt = NULL;
ShbError = ShbCirReleaseBuffer(EplDllkCalInstance_g.m_ShbInstanceTxGen);
if (ShbError != kShbOk) {
Ret = kEplNoResource;
}
EplDllkCalInstance_g.m_ShbInstanceTxGen = NULL;
#else
EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
#endif
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalProcess
//
// Description: process the passed configuration
//
// Parameters: pEvent_p = event containing configuration options
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p)
{
tEplKernel Ret = kEplSuccessful;
switch (pEvent_p->m_EventType) {
case kEplEventTypeDllkServFilter:
{
tEplDllCalAsndServiceIdFilter *pServFilter;
pServFilter =
(tEplDllCalAsndServiceIdFilter *) pEvent_p->m_pArg;
Ret =
EplDllkSetAsndServiceIdFilter(pServFilter->
m_ServiceId,
pServFilter->
m_Filter);
break;
}
#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
case kEplEventTypeDllkIssueReq:
{
tEplDllCalIssueRequest *pIssueReq;
pIssueReq = (tEplDllCalIssueRequest *) pEvent_p->m_pArg;
Ret =
EplDllkCalIssueRequest(pIssueReq->m_Service,
pIssueReq->m_uiNodeId,
pIssueReq->m_bSoaFlag1);
break;
}
case kEplEventTypeDllkAddNode:
{
tEplDllNodeInfo *pNodeInfo;
pNodeInfo = (tEplDllNodeInfo *) pEvent_p->m_pArg;
Ret = EplDllkAddNode(pNodeInfo);
break;
}
case kEplEventTypeDllkDelNode:
{
unsigned int *puiNodeId;
puiNodeId = (unsigned int *)pEvent_p->m_pArg;
Ret = EplDllkDeleteNode(*puiNodeId);
break;
}
case kEplEventTypeDllkSoftDelNode:
{
unsigned int *puiNodeId;
puiNodeId = (unsigned int *)pEvent_p->m_pArg;
Ret = EplDllkSoftDeleteNode(*puiNodeId);
break;
}
#endif
case kEplEventTypeDllkIdentity:
{
tEplDllIdentParam *pIdentParam;
pIdentParam = (tEplDllIdentParam *) pEvent_p->m_pArg;
if (pIdentParam->m_uiSizeOfStruct > pEvent_p->m_uiSize) {
pIdentParam->m_uiSizeOfStruct =
pEvent_p->m_uiSize;
}
Ret = EplDllkSetIdentity(pIdentParam);
break;
}
case kEplEventTypeDllkConfig:
{
tEplDllConfigParam *pConfigParam;
pConfigParam = (tEplDllConfigParam *) pEvent_p->m_pArg;
if (pConfigParam->m_uiSizeOfStruct > pEvent_p->m_uiSize) {
pConfigParam->m_uiSizeOfStruct =
pEvent_p->m_uiSize;
}
Ret = EplDllkConfig(pConfigParam);
break;
}
default:
break;
}
//Exit:
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncGetTxCount()
//
// Description: returns count of Tx frames of FIFO with highest priority
//
// Parameters: none
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncGetTxCount(tEplDllAsyncReqPriority * pPriority_p,
unsigned int *puiCount_p)
{
tEplKernel Ret = kEplSuccessful;
#ifndef EPL_NO_FIFO
tShbError ShbError;
unsigned long ulFrameCount;
// get frame count of Tx FIFO with NMT request priority
ShbError =
ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxNmt,
&ulFrameCount);
// returns kShbOk, kShbInvalidArg
// error handling
if (ShbError != kShbOk) {
Ret = kEplNoResource;
goto Exit;
}
if (ulFrameCount >
EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt) {
EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt =
ulFrameCount;
}
if (ulFrameCount != 0) { // NMT requests are in queue
*pPriority_p = kEplDllAsyncReqPrioNmt;
*puiCount_p = (unsigned int)ulFrameCount;
goto Exit;
}
// get frame count of Tx FIFO with generic priority
ShbError =
ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxGen,
&ulFrameCount);
// returns kShbOk, kShbInvalidArg
// error handling
if (ShbError != kShbOk) {
Ret = kEplNoResource;
goto Exit;
}
if (ulFrameCount >
EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen) {
EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen =
ulFrameCount;
}
*pPriority_p = kEplDllAsyncReqPrioGeneric;
*puiCount_p = (unsigned int)ulFrameCount;
Exit:
#else
if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0) {
*pPriority_p = kEplDllAsyncReqPrioNmt;
*puiCount_p = 1;
} else if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0) {
*pPriority_p = kEplDllAsyncReqPrioGeneric;
*puiCount_p = 1;
} else {
*pPriority_p = kEplDllAsyncReqPrioGeneric;
*puiCount_p = 0;
}
#endif
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncGetTxFrame()
//
// Description: returns Tx frames from FIFO with specified priority
//
// Parameters: pFrame_p = IN: pointer to buffer
// puiFrameSize_p = IN: max size of buffer
// OUT: actual size of frame
// Priority_p = IN: priority
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncGetTxFrame(void *pFrame_p,
unsigned int *puiFrameSize_p,
tEplDllAsyncReqPriority Priority_p)
{
tEplKernel Ret = kEplSuccessful;
#ifndef EPL_NO_FIFO
tShbError ShbError;
unsigned long ulFrameSize;
switch (Priority_p) {
case kEplDllAsyncReqPrioNmt: // NMT request priority
ShbError =
ShbCirReadDataBlock(EplDllkCalInstance_g.m_ShbInstanceTxNmt,
(u8 *) pFrame_p, *puiFrameSize_p,
&ulFrameSize);
// returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData
break;
default: // generic priority
ShbError =
ShbCirReadDataBlock(EplDllkCalInstance_g.m_ShbInstanceTxGen,
(u8 *) pFrame_p, *puiFrameSize_p,
&ulFrameSize);
// returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData
break;
}
// error handling
if (ShbError != kShbOk) {
if (ShbError == kShbNoReadableData) {
Ret = kEplDllAsyncTxBufferEmpty;
} else { // other error
Ret = kEplNoResource;
}
goto Exit;
}
*puiFrameSize_p = (unsigned int)ulFrameSize;
Exit:
#else
switch (Priority_p) {
case kEplDllAsyncReqPrioNmt: // NMT request priority
*puiFrameSize_p =
min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeNmt);
EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameNmt,
*puiFrameSize_p);
EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
break;
default: // generic priority
*puiFrameSize_p =
min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeGen);
EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameGen,
*puiFrameSize_p);
EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
break;
}
#endif
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncFrameReceived()
//
// Description: passes ASnd frame to receive FIFO.
// It will be called only for frames with registered AsndServiceIds.
//
// Parameters: none
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncFrameReceived(tEplFrameInfo * pFrameInfo_p)
{
tEplKernel Ret = kEplSuccessful;
tEplEvent Event;
Event.m_EventSink = kEplEventSinkDlluCal;
Event.m_EventType = kEplEventTypeAsndRx;
Event.m_pArg = pFrameInfo_p->m_pFrame;
Event.m_uiSize = pFrameInfo_p->m_uiFrameSize;
// pass NetTime of frame to userspace
Event.m_NetTime = pFrameInfo_p->m_NetTime;
Ret = EplEventkPost(&Event);
if (Ret != kEplSuccessful) {
EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount++;
} else {
EplDllkCalInstance_g.m_Statistics.m_ulMaxRxFrameCount++;
}
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncSend()
//
// Description: puts the given frame into the transmit FIFO with the specified
// priority.
//
// Parameters: pFrameInfo_p = frame info structure
// Priority_p = priority
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p,
tEplDllAsyncReqPriority Priority_p)
{
tEplKernel Ret = kEplSuccessful;
tEplEvent Event;
#ifndef EPL_NO_FIFO
tShbError ShbError;
switch (Priority_p) {
case kEplDllAsyncReqPrioNmt: // NMT request priority
ShbError =
ShbCirWriteDataBlock(EplDllkCalInstance_g.
m_ShbInstanceTxNmt,
pFrameInfo_p->m_pFrame,
pFrameInfo_p->m_uiFrameSize);
// returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg
break;
default: // generic priority
ShbError =
ShbCirWriteDataBlock(EplDllkCalInstance_g.
m_ShbInstanceTxGen,
pFrameInfo_p->m_pFrame,
pFrameInfo_p->m_uiFrameSize);
// returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg
break;
}
// error handling
switch (ShbError) {
case kShbOk:
break;
case kShbExceedDataSizeLimit:
Ret = kEplDllAsyncTxBufferFull;
break;
case kShbBufferFull:
Ret = kEplDllAsyncTxBufferFull;
break;
case kShbInvalidArg:
default:
Ret = kEplNoResource;
break;
}
#else
switch (Priority_p) {
case kEplDllAsyncReqPrioNmt: // NMT request priority
if (EplDllkCalInstance_g.m_uiFrameSizeNmt == 0) {
EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameNmt,
pFrameInfo_p->m_pFrame,
pFrameInfo_p->m_uiFrameSize);
EplDllkCalInstance_g.m_uiFrameSizeNmt =
pFrameInfo_p->m_uiFrameSize;
} else {
Ret = kEplDllAsyncTxBufferFull;
goto Exit;
}
break;
default: // generic priority
if (EplDllkCalInstance_g.m_uiFrameSizeGen == 0) {
EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameGen,
pFrameInfo_p->m_pFrame,
pFrameInfo_p->m_uiFrameSize);
EplDllkCalInstance_g.m_uiFrameSizeGen =
pFrameInfo_p->m_uiFrameSize;
} else {
Ret = kEplDllAsyncTxBufferFull;
goto Exit;
}
break;
}
#endif
// post event to DLL
Event.m_EventSink = kEplEventSinkDllk;
Event.m_EventType = kEplEventTypeDllkFillTx;
EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
Event.m_pArg = &Priority_p;
Event.m_uiSize = sizeof(Priority_p);
Ret = EplEventkPost(&Event);
#ifdef EPL_NO_FIFO
Exit:
#endif
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncClearBuffer()
//
// Description: clears the transmit buffer
//
// Parameters: (none)
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncClearBuffer(void)
{
tEplKernel Ret = kEplSuccessful;
#ifndef EPL_NO_FIFO
tShbError ShbError;
ShbError =
ShbCirResetBuffer(EplDllkCalInstance_g.m_ShbInstanceTxNmt, 1000,
NULL);
ShbError =
ShbCirResetBuffer(EplDllkCalInstance_g.m_ShbInstanceTxGen, 1000,
NULL);
#else
EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
#endif
// EPL_MEMSET(&EplDllkCalInstance_g.m_Statistics, 0, sizeof (tEplDllkCalStatistics));
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncClearQueues()
//
// Description: clears the transmit buffer
//
// Parameters: (none)
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
tEplKernel EplDllkCalAsyncClearQueues(void)
{
tEplKernel Ret = kEplSuccessful;
// clear MN asynchronous queues
EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
EplDllkCalInstance_g.m_uiNextRequestQueue = 0;
EplDllkCalInstance_g.m_uiReadIdentReq = 0;
EplDllkCalInstance_g.m_uiWriteIdentReq = 0;
EplDllkCalInstance_g.m_uiReadStatusReq = 0;
EplDllkCalInstance_g.m_uiWriteStatusReq = 0;
return Ret;
}
#endif
//---------------------------------------------------------------------------
//
// Function: EplDllkCalGetStatistics()
//
// Description: returns statistics of the asynchronous queues.
//
// Parameters: ppStatistics = statistics structure
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics)
{
tEplKernel Ret = kEplSuccessful;
#ifndef EPL_NO_FIFO
tShbError ShbError;
ShbError =
ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxNmt,
&EplDllkCalInstance_g.m_Statistics.
m_ulCurTxFrameCountNmt);
ShbError =
ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxGen,
&EplDllkCalInstance_g.m_Statistics.
m_ulCurTxFrameCountGen);
// ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceRx, &EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount);
#else
if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0) {
EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 1;
} else {
EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 0;
}
if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0) {
EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 1;
} else {
EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 0;
}
#endif
*ppStatistics = &EplDllkCalInstance_g.m_Statistics;
return Ret;
}
#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
//---------------------------------------------------------------------------
//
// Function: EplDllkCalIssueRequest()
//
// Description: issues a StatusRequest or a IdentRequest to the specified node.
//
// Parameters: Service_p = request service ID
// uiNodeId_p = node ID
// bSoaFlag1_p = flag1 for this node (transmit in SoA and PReq)
// If 0xFF this flag is ignored.
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p,
unsigned int uiNodeId_p, u8 bSoaFlag1_p)
{
tEplKernel Ret = kEplSuccessful;
if (bSoaFlag1_p != 0xFF) {
Ret = EplDllkSetFlag1OfNode(uiNodeId_p, bSoaFlag1_p);
if (Ret != kEplSuccessful) {
goto Exit;
}
}
// add node to appropriate request queue
switch (Service_p) {
case kEplDllReqServiceIdent:
{
if (((EplDllkCalInstance_g.m_uiWriteIdentReq +
1) %
tabentries(EplDllkCalInstance_g.
m_auiQueueIdentReq))
== EplDllkCalInstance_g.m_uiReadIdentReq) { // queue is full
Ret = kEplDllAsyncTxBufferFull;
goto Exit;
}
EplDllkCalInstance_g.
m_auiQueueIdentReq[EplDllkCalInstance_g.
m_uiWriteIdentReq] = uiNodeId_p;
EplDllkCalInstance_g.m_uiWriteIdentReq =
(EplDllkCalInstance_g.m_uiWriteIdentReq +
1) %
tabentries(EplDllkCalInstance_g.m_auiQueueIdentReq);
break;
}
case kEplDllReqServiceStatus:
{
if (((EplDllkCalInstance_g.m_uiWriteStatusReq +
1) %
tabentries(EplDllkCalInstance_g.
m_auiQueueStatusReq))
== EplDllkCalInstance_g.m_uiReadStatusReq) { // queue is full
Ret = kEplDllAsyncTxBufferFull;
goto Exit;
}
EplDllkCalInstance_g.
m_auiQueueStatusReq[EplDllkCalInstance_g.
m_uiWriteStatusReq] =
uiNodeId_p;
EplDllkCalInstance_g.m_uiWriteStatusReq =
(EplDllkCalInstance_g.m_uiWriteStatusReq +
1) %
tabentries(EplDllkCalInstance_g.
m_auiQueueStatusReq);
break;
}
default:
{
Ret = kEplDllInvalidParam;
goto Exit;
}
}
Exit:
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncGetSoaRequest()
//
// Description: returns next request for SoA. This function is called by DLLk module.
//
// Parameters: pReqServiceId_p = pointer to request service ID
// IN: available request for MN NMT or generic request queue (Flag2.PR)
// or kEplDllReqServiceNo if queues are empty
// OUT: next request
// puiNodeId_p = OUT: pointer to node ID of next request
// = EPL_C_ADR_INVALID, if request is self addressed
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId * pReqServiceId_p,
unsigned int *puiNodeId_p)
{
tEplKernel Ret = kEplSuccessful;
unsigned int uiCount;
// *pReqServiceId_p = kEplDllReqServiceNo;
for (uiCount = EPL_DLLKCAL_MAX_QUEUES; uiCount > 0; uiCount--) {
switch (EplDllkCalInstance_g.m_uiNextRequestQueue) {
case 0:
{ // CnGenReq
for (;
EplDllkCalInstance_g.
m_uiNextQueueCnRequest <
(tabentries
(EplDllkCalInstance_g.
m_auiQueueCnRequests) / 2);
EplDllkCalInstance_g.
m_uiNextQueueCnRequest++) {
if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0) { // non empty queue found
// remove one request from queue
EplDllkCalInstance_g.
m_auiQueueCnRequests
[EplDllkCalInstance_g.
m_uiNextQueueCnRequest]--;
*puiNodeId_p =
EplDllkCalInstance_g.
m_uiNextQueueCnRequest + 1;
*pReqServiceId_p =
kEplDllReqServiceUnspecified;
EplDllkCalInstance_g.
m_uiNextQueueCnRequest++;
if (EplDllkCalInstance_g.m_uiNextQueueCnRequest >= (tabentries(EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) { // last node reached
// continue with CnNmtReq queue at next SoA
EplDllkCalInstance_g.
m_uiNextRequestQueue
= 1;
}
goto Exit;
}
}
// all CnGenReq queues are empty -> continue with CnNmtReq queue
EplDllkCalInstance_g.m_uiNextRequestQueue = 1;
break;
}
case 1:
{ // CnNmtReq
for (;
EplDllkCalInstance_g.
m_uiNextQueueCnRequest <
tabentries(EplDllkCalInstance_g.
m_auiQueueCnRequests);
EplDllkCalInstance_g.
m_uiNextQueueCnRequest++) {
if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0) { // non empty queue found
// remove one request from queue
EplDllkCalInstance_g.
m_auiQueueCnRequests
[EplDllkCalInstance_g.
m_uiNextQueueCnRequest]--;
*puiNodeId_p =
EplDllkCalInstance_g.
m_uiNextQueueCnRequest + 1 -
(tabentries
(EplDllkCalInstance_g.
m_auiQueueCnRequests) /
2);
*pReqServiceId_p =
kEplDllReqServiceNmtRequest;
EplDllkCalInstance_g.
m_uiNextQueueCnRequest++;
if (EplDllkCalInstance_g.m_uiNextQueueCnRequest > tabentries(EplDllkCalInstance_g.m_auiQueueCnRequests)) { // last node reached
// restart CnGenReq queue
EplDllkCalInstance_g.
m_uiNextQueueCnRequest
= 0;
// continue with MnGenReq queue at next SoA
EplDllkCalInstance_g.
m_uiNextRequestQueue
= 2;
}
goto Exit;
}
}
// restart CnGenReq queue
EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
// all CnNmtReq queues are empty -> continue with MnGenReq queue
EplDllkCalInstance_g.m_uiNextRequestQueue = 2;
break;
}
case 2:
{ // MnNmtReq and MnGenReq
// next queue will be MnIdentReq queue
EplDllkCalInstance_g.m_uiNextRequestQueue = 3;
if (*pReqServiceId_p != kEplDllReqServiceNo) {
*puiNodeId_p = EPL_C_ADR_INVALID; // DLLk must exchange this with the actual node ID
goto Exit;
}
break;
}
case 3:
{ // MnIdentReq
// next queue will be MnStatusReq queue
EplDllkCalInstance_g.m_uiNextRequestQueue = 4;
if (EplDllkCalInstance_g.m_uiReadIdentReq != EplDllkCalInstance_g.m_uiWriteIdentReq) { // queue is not empty
*puiNodeId_p =
EplDllkCalInstance_g.
m_auiQueueIdentReq
[EplDllkCalInstance_g.
m_uiReadIdentReq];
EplDllkCalInstance_g.m_uiReadIdentReq =
(EplDllkCalInstance_g.
m_uiReadIdentReq +
1) %
tabentries(EplDllkCalInstance_g.
m_auiQueueIdentReq);
*pReqServiceId_p =
kEplDllReqServiceIdent;
goto Exit;
}
break;
}
case 4:
{ // MnStatusReq
// next queue will be CnGenReq queue
EplDllkCalInstance_g.m_uiNextRequestQueue = 0;
if (EplDllkCalInstance_g.m_uiReadStatusReq != EplDllkCalInstance_g.m_uiWriteStatusReq) { // queue is not empty
*puiNodeId_p =
EplDllkCalInstance_g.
m_auiQueueStatusReq
[EplDllkCalInstance_g.
m_uiReadStatusReq];
EplDllkCalInstance_g.m_uiReadStatusReq =
(EplDllkCalInstance_g.
m_uiReadStatusReq +
1) %
tabentries(EplDllkCalInstance_g.
m_auiQueueStatusReq);
*pReqServiceId_p =
kEplDllReqServiceStatus;
goto Exit;
}
break;
}
}
}
Exit:
return Ret;
}
//---------------------------------------------------------------------------
//
// Function: EplDllkCalAsyncSetPendingRequests()
//
// Description: sets the pending asynchronous frame requests of the specified node.
// This will add the node to the asynchronous request scheduler.
//
// Parameters: uiNodeId_p = node ID
// AsyncReqPrio_p = asynchronous request priority
// uiCount_p = count of asynchronous frames
//
// Returns: tEplKernel = error code
//
//
// State:
//
//---------------------------------------------------------------------------
tEplKernel EplDllkCalAsyncSetPendingRequests(unsigned int uiNodeId_p,
tEplDllAsyncReqPriority
AsyncReqPrio_p,
unsigned int uiCount_p)
{
tEplKernel Ret = kEplSuccessful;
// add node to appropriate request queue
switch (AsyncReqPrio_p) {
case kEplDllAsyncReqPrioNmt:
{
uiNodeId_p--;
if (uiNodeId_p >=
(tabentries
(EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) {
Ret = kEplDllInvalidParam;
goto Exit;
}
uiNodeId_p +=
tabentries(EplDllkCalInstance_g.
m_auiQueueCnRequests) / 2;
EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] =
uiCount_p;
break;
}
default:
{
uiNodeId_p--;
if (uiNodeId_p >=
(tabentries
(EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) {
Ret = kEplDllInvalidParam;
goto Exit;
}
EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] =
uiCount_p;
break;
}
}
Exit:
return Ret;
}
#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 //
// //
//=========================================================================//
//---------------------------------------------------------------------------
// Callback handler for new data signaling
//---------------------------------------------------------------------------
#ifndef EPL_NO_FIFO
/*static void EplDllkCalTxNmtSignalHandler (
tShbInstance pShbRxInstance_p,
unsigned long ulDataSize_p)
{
tEplKernel Ret = kEplSuccessful;
tEplEvent Event;
tEplDllAsyncReqPriority Priority;
#ifndef EPL_NO_FIFO
tShbError ShbError;
unsigned long ulBlockCount;
ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &ulBlockCount);
if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt)
{
EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt = ulBlockCount;
}
#endif
// 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);
}
static void EplDllkCalTxGenSignalHandler (
tShbInstance pShbRxInstance_p,
unsigned long ulDataSize_p)
{
tEplKernel Ret = kEplSuccessful;
tEplEvent Event;
tEplDllAsyncReqPriority Priority;
#ifndef EPL_NO_FIFO
tShbError ShbError;
unsigned long ulBlockCount;
ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &ulBlockCount);
if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen)
{
EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen = ulBlockCount;
}
#endif
// 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);
}
*/
#endif
#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
// EOF