| /**************************************************************************** |
| |
| (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 |