示例#1
0
//------------------------------------------------------------------------------
static tOplkError processFillTx(tDllAsyncReqPriority asyncReqPriority_p, tNmtState nmtState_p)
{
    tOplkError      ret = kErrorOk;
    tPlkFrame *     pTxFrame;
    tEdrvTxBuffer*  pTxBuffer;
    UINT            frameSize;
    UINT            frameCount;
    UINT            nextTxBufferOffset;
    tDllkTxBufState* pTxBufferState = NULL;
#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
    UINT            filterEntry;
#endif

    // fill TxBuffer of specified priority with new frame if empty
    pTxFrame = NULL;
    switch (asyncReqPriority_p)
    {
        case kDllAsyncReqPrioNmt:    // NMT request priority
            nextTxBufferOffset = dllkInstance_g.curTxBufferOffsetNmtReq;
            pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_NMTREQ + nextTxBufferOffset];
            pTxBufferState = &dllkInstance_g.aTxBufferStateNmtReq[nextTxBufferOffset];
#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
            filterEntry = DLLK_FILTER_SOA_NMTREQ;
#endif
            break;

        default:    // generic priority
            nextTxBufferOffset = dllkInstance_g.curTxBufferOffsetNonPlk;
            pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_NONPLK + nextTxBufferOffset];
            pTxBufferState = &dllkInstance_g.aTxBufferStateNonPlk[nextTxBufferOffset];
#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
            filterEntry = DLLK_FILTER_SOA_NONPLK;
#endif
            break;
    }

    if (pTxBuffer->pBuffer != NULL)
    {   // NmtRequest or non-POWERLINK frame does exist
        // check if frame is empty and not being filled
        if (*pTxBufferState == kDllkTxBufEmpty)
        {
            *pTxBufferState = kDllkTxBufFilling;              // mark Tx buffer as filling is in process
            frameSize = pTxBuffer->maxBufferSize;            // set max buffer size as input parameter

            // copy frame from shared loop buffer to Tx buffer
            ret = dllkcal_getAsyncTxFrame(pTxBuffer->pBuffer, &frameSize, asyncReqPriority_p);
            if (ret == kErrorOk)
            {
                pTxFrame = (tPlkFrame*)pTxBuffer->pBuffer;
                ret = dllkframe_checkFrame(pTxFrame, frameSize);
                if (ret != kErrorOk)
                    goto Exit;

                pTxBuffer->txFrameSize = frameSize;    // set buffer valid
                *pTxBufferState = kDllkTxBufReady;

#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
                if ((nmtState_p & (NMT_TYPE_MASK | NMT_SUPERSTATE_MASK)) == (NMT_TYPE_CS | NMT_CS_PLKMODE))
                {
                    ret = edrv_updateTxBuffer(pTxBuffer);

                    // enable corresponding Rx filter
                    dllkInstance_g.aFilter[filterEntry].fEnable = TRUE;
                    ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                           filterEntry, EDRV_FILTER_CHANGE_STATE);
                    if (ret != kErrorOk)
                        goto Exit;
                }
#endif
            }
            else if (ret == kErrorDllAsyncTxBufferEmpty)
            {   // empty Tx buffer is not a real problem so just ignore it
                ret = kErrorOk;

                *pTxBufferState = kDllkTxBufEmpty;    // mark Tx buffer as empty

#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
                if ((nmtState_p & (NMT_TYPE_MASK | NMT_SUPERSTATE_MASK)) == (NMT_TYPE_CS | NMT_CS_PLKMODE))
                {
                    // disable corresponding Rx filter
                    dllkInstance_g.aFilter[filterEntry].fEnable = FALSE;
                    ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                           filterEntry, EDRV_FILTER_CHANGE_STATE);
                    if (ret != kErrorOk)
                        goto Exit;
                }
#endif
            }
            else
            {
                goto Exit;
            }
        }
    }

    if ((nmtState_p == kNmtCsBasicEthernet) || (nmtState_p == kNmtMsBasicEthernet))
    {   // send frame immediately
        if (pTxFrame != NULL)
        {   // frame is present - padding is done by Edrv or ethernet controller
            *pTxBufferState = kDllkTxBufSending;
            ret = edrv_sendTxBuffer(pTxBuffer);
        }
        else
        {   // no frame moved to TxBuffer

            // check if TxBuffers contain unsent frames
            if (dllkInstance_g.aTxBufferStateNmtReq[dllkInstance_g.curTxBufferOffsetNmtReq] == kDllkTxBufReady)
            {   // NMT request Tx buffer contains a frame
                dllkInstance_g.aTxBufferStateNmtReq[dllkInstance_g.curTxBufferOffsetNmtReq] = kDllkTxBufSending;
                ret = edrv_sendTxBuffer(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_NMTREQ +
                                                              dllkInstance_g.curTxBufferOffsetNmtReq]);
            }
            else if (dllkInstance_g.aTxBufferStateNonPlk[dllkInstance_g.curTxBufferOffsetNonPlk] == kDllkTxBufReady)
            {   // non-POWERLINK Tx buffer contains a frame
                dllkInstance_g.aTxBufferStateNonPlk[dllkInstance_g.curTxBufferOffsetNonPlk] = kDllkTxBufSending;
                ret = edrv_sendTxBuffer(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_NONPLK +
                                                              dllkInstance_g.curTxBufferOffsetNonPlk]);
            }
            if (ret == kErrorInvalidOperation)
            {   // ignore error if caused by already active transmission
                ret = kErrorOk;
            }
        }
        dllkInstance_g.flag2 = 0;               // reset PRes flag 2
    }
    else
    {
        // update Flag 2 (PR, RS)
        ret = dllkcal_getAsyncTxCount(&asyncReqPriority_p, &frameCount);
        if (asyncReqPriority_p == kDllAsyncReqPrioNmt)
        {   // non-empty FIFO with hightest priority is for NMT requests
            if (dllkInstance_g.aTxBufferStateNmtReq[dllkInstance_g.curTxBufferOffsetNmtReq] == kDllkTxBufReady)
            {   // NMT request Tx buffer contains a frame
                // add one more frame
                frameCount++;
            }
        }
        else
        {   // non-empty FIFO with highest priority is for generic frames
            if (dllkInstance_g.aTxBufferStateNmtReq[dllkInstance_g.curTxBufferOffsetNmtReq] == kDllkTxBufReady)
            {   // NMT request Tx buffer contains a frame
                // use NMT request FIFO, because of higher priority
                frameCount = 1;
                asyncReqPriority_p = kDllAsyncReqPrioNmt;
            }
            else if (dllkInstance_g.aTxBufferStateNonPlk[dllkInstance_g.curTxBufferOffsetNonPlk] == kDllkTxBufReady)
            {   // non-POWERLINK Tx buffer contains a frame
                // use NMT request FIFO, because of higher priority
                // add one more frame
                frameCount++;
            }
        }

        if (frameCount > 7)
        {   // limit frame request to send counter to 7
            frameCount = 7;
        }
        if (frameCount > 0)
        {
            dllkInstance_g.flag2 = (UINT8)(((asyncReqPriority_p << PLK_FRAME_FLAG2_PR_SHIFT) &
                                             PLK_FRAME_FLAG2_PR) | (frameCount & PLK_FRAME_FLAG2_RS));
        }
        else
        {
            dllkInstance_g.flag2 = 0;
        }
        dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH;
    }

Exit:
    return ret;
}
示例#2
0
//------------------------------------------------------------------------------
static tOplkError processNmtStateChange(tNmtState newNmtState_p,
                                        tNmtState oldNmtState_p, tNmtEvent nmtEvent_p)
{
    tOplkError      ret = kErrorOk;

#if !defined(CONFIG_INCLUDE_NMT_RMN)
    UNUSED_PARAMETER(nmtEvent_p);
#endif

    switch (newNmtState_p)
    {
        case kNmtGsOff:
        case kNmtGsInitialising:
            dllkInstance_g.socTime.relTime = 0;
            // set EC flag in Flag 1, so the MN can detect a reboot and
            // will initialize the Error Signaling.
            dllkInstance_g.flag1 = PLK_FRAME_FLAG1_EC;
            dllkInstance_g.nmtState = newNmtState_p;
            if (oldNmtState_p > kNmtGsResetConfiguration)
            {
                ret = dllknode_cleanupLocalNode(oldNmtState_p);      // deinitialize DLL and destroy frames
            }
            break;

        case kNmtGsResetApplication:
        case kNmtGsResetCommunication:
        case kNmtGsResetConfiguration:
            // at first, update NMT state in instance structure to disable frame processing
            dllkInstance_g.nmtState = newNmtState_p;
            if (oldNmtState_p > kNmtGsResetConfiguration)
            {
                ret = dllknode_cleanupLocalNode(oldNmtState_p);      // deinitialize DLL and destroy frames

            }
            break;

        // node listens for POWERLINK frames and check timeout
        case kNmtMsNotActive:
        case kNmtCsNotActive:
        case kNmtRmsNotActive:
            if (oldNmtState_p <= kNmtGsResetConfiguration)
            {
                // setup DLL and create frames
                ret = dllknode_setupLocalNode(newNmtState_p);
            }
            break;

        // node processes only async frames
        case kNmtCsPreOperational1:
#if CONFIG_TIMER_USE_HIGHRES != FALSE
            if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlCycle)) != kErrorOk)
                return ret;
#endif

#if defined(CONFIG_INCLUDE_NMT_RMN)
            if (dllkInstance_g.fRedundancy)
            {
                ret = edrvcyclic_stopCycle(FALSE);
                if (ret != kErrorOk)
                    return ret;

                hrestimer_modifyTimer(&dllkInstance_g.timerHdlSwitchOver,
                                      dllkInstance_g.dllConfigParam.reducedSwitchOverTimeMn * 1000ULL,
                                      dllk_cbTimerSwitchOver, 0L, FALSE);
            }
#endif

            // deactivate sync generation
            if ((ret = controlTimeSync(FALSE)) != kErrorOk)
                return ret;

#if (CONFIG_DLL_PROCESS_SYNC == DLL_PROCESS_SYNC_ON_TIMER)
            if ((ret = synctimer_stopSync()) != kErrorOk)
                return ret;
#endif

#if CONFIG_DLL_PRES_CHAINING_CN != FALSE
            if ((ret = dllkframe_presChainingDisable()) != kErrorOk)
                return ret;
#endif

            // update IdentRes and StatusRes
            ret = dllkframe_updateFrameStatusRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_STATUSRES +
                                                     dllkInstance_g.curTxBufferOffsetStatusRes],
                                                 newNmtState_p);
            if (ret != kErrorOk)
                return ret;

            ret = dllkframe_updateFrameIdentRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_IDENTRES +
                                                    dllkInstance_g.curTxBufferOffsetIdentRes],
                                                newNmtState_p);
            if (ret != kErrorOk)
                return ret;

            // enable IdentRes and StatusRes
#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
            // enable corresponding Rx filter
            dllkInstance_g.aFilter[DLLK_FILTER_SOA_STATREQ].fEnable = TRUE;
            ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                   DLLK_FILTER_SOA_STATREQ, EDRV_FILTER_CHANGE_STATE);
            if (ret != kErrorOk)
                return ret;

            // enable corresponding Rx filter
            dllkInstance_g.aFilter[DLLK_FILTER_SOA_IDREQ].fEnable = TRUE;
            ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                   DLLK_FILTER_SOA_IDREQ, EDRV_FILTER_CHANGE_STATE);
            if (ret != kErrorOk)
                return ret;

#if CONFIG_DLL_PRES_CHAINING_CN != FALSE
            // enable SyncReq Rx filter
            dllkInstance_g.aFilter[DLLK_FILTER_SOA_SYNCREQ].fEnable = TRUE;
            ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                   DLLK_FILTER_SOA_SYNCREQ, EDRV_FILTER_CHANGE_STATE);
            if (ret != kErrorOk)
                return ret;
#endif
#endif

            // update PRes (for sudden changes to PreOp2)
            ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES +
                                            (dllkInstance_g.curTxBufferOffsetCycle ^ 1)],
                                            kNmtCsPreOperational2);
            if (ret != kErrorOk)
                return ret;

            ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES +
                                            dllkInstance_g.curTxBufferOffsetCycle],
                                            kNmtCsPreOperational2);
            if (ret != kErrorOk)
                return ret;

            // enable PRes (for sudden changes to PreOp2)
#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
            // enable corresponding Rx filter
            dllkInstance_g.aFilter[DLLK_FILTER_PREQ].fEnable = TRUE;
            dllkInstance_g.aFilter[DLLK_FILTER_PREQ].pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES];
            ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                   DLLK_FILTER_PREQ, EDRV_FILTER_CHANGE_STATE | EDRV_FILTER_CHANGE_AUTO_RESPONSE);
            if (ret != kErrorOk)
                return ret;
#endif
            break;

        // node processes isochronous and asynchronous frames
        case kNmtCsPreOperational2:
            // signal update of IdentRes and StatusRes on SoA
            dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH;

            // enable PRes (necessary if coming from Stopped)
#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
            // enable corresponding Rx filter
            dllkInstance_g.aFilter[DLLK_FILTER_PREQ].fEnable = TRUE;
            dllkInstance_g.aFilter[DLLK_FILTER_PREQ].pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES];
            ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                   DLLK_FILTER_PREQ, EDRV_FILTER_CHANGE_STATE | EDRV_FILTER_CHANGE_AUTO_RESPONSE);
            if (ret != kErrorOk)
                return ret;
#endif
            break;

#if defined (CONFIG_INCLUDE_NMT_MN)
        case kNmtMsPreOperational1:
#if CONFIG_TIMER_USE_HIGHRES != FALSE
            ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlCycle);
            if (ret != kErrorOk)
                return ret;
#endif
            /// deactivate sync generation
            if ((ret = controlTimeSync(FALSE)) != kErrorOk)
                return ret;

            ret = edrvcyclic_stopCycle(FALSE);
            if (ret != kErrorOk)
                return ret;

#if defined(CONFIG_INCLUDE_NMT_RMN)
            if (dllkInstance_g.fRedundancy)
            {
                if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlSwitchOver)) != kErrorOk)
                    return ret;

                if (oldNmtState_p == kNmtRmsNotActive)
                {   // send AMNI
                    ret = edrv_sendTxBuffer(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_AMNI]);
                    if (ret != kErrorOk)
                        return ret;
                }

                // initialize cycle counter
                if (dllkInstance_g.dllConfigParam.fAsyncOnly == FALSE)
                {
                    dllkInstance_g.cycleCount = 0;
                }
                else
                {   // it is an async-only CN -> fool changeState() to think that PRes was not expected
                    dllkInstance_g.cycleCount = 1;
                }
            }
#endif

            // update IdentRes and StatusRes
            ret = dllkframe_updateFrameIdentRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_IDENTRES +
                                                    dllkInstance_g.curTxBufferOffsetIdentRes],
                                                newNmtState_p);
            if (ret != kErrorOk)
                return ret;

            ret = dllkframe_updateFrameStatusRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_STATUSRES +
                                                     dllkInstance_g.curTxBufferOffsetStatusRes],
                                                 newNmtState_p);
            break;

        case kNmtMsReadyToOperate:
            /// activate sync generation
            if ((ret = controlTimeSync(TRUE)) != kErrorOk)
                return ret;
            break;

        case kNmtMsPreOperational2:
        case kNmtMsOperational:
            // signal update of IdentRes and StatusRes on SoA
            dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH;

#if defined(CONFIG_INCLUDE_NMT_RMN)
            if (dllkInstance_g.fRedundancy && (oldNmtState_p == kNmtCsOperational))
            {
                dllkInstance_g.dllState = kDllMsWaitSocTrig;
                if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlSwitchOver)) != kErrorOk)
                    return ret;

                dllkInstance_g.socTime.relTime += dllkInstance_g.dllConfigParam.cycleLen;
                // initialize SoAReq number for ProcessSync (cycle preparation)
                dllkInstance_g.syncLastSoaReq = dllkInstance_g.curLastSoaReq;
                // trigger synchronous task for cycle preparation
                dllkInstance_g.fSyncProcessed = TRUE;
                ret = dllk_postEvent(kEventTypeSync);
            }
#endif
            break;

#endif

        case kNmtCsReadyToOperate:
            /// activate sync generation
            if ((ret = controlTimeSync(TRUE)) != kErrorOk)
                return ret;
            // signal update of IdentRes and StatusRes on SoA
            dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH;
            break;

        case kNmtCsOperational:
            // signal update of IdentRes and StatusRes on SoA
            dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH;
#if defined(CONFIG_INCLUDE_NMT_RMN)
            if (dllkInstance_g.fRedundancy && (oldNmtState_p == kNmtMsOperational))
            {
                dllkInstance_g.dllState = kDllCsWaitSoc;
                ret = edrvcyclic_stopCycle(TRUE);
                if (ret != kErrorOk)
                    return ret;

                hrestimer_modifyTimer(&dllkInstance_g.timerHdlSwitchOver,
                                      dllkInstance_g.dllConfigParam.switchOverTimeMn * 1000ULL,
                                      dllk_cbTimerSwitchOver, 0L, FALSE);

                if ((nmtEvent_p == kNmtEventGoToStandby) || (nmtEvent_p == kNmtEventGoToStandbyDelayed))
                {   // save event, so cbCyclicError can start switch-over timeout
                    // appropriately
                    dllkInstance_g.nmtEventGoToStandby = nmtEvent_p;
                }
            }
#endif
            break;

        // node stopped by MN
        case kNmtCsStopped:
            // signal update of IdentRes and StatusRes on SoA
            dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH;

#if (CONFIG_EDRV_AUTO_RESPONSE != FALSE)
            // disable auto-response for PRes filter
            dllkInstance_g.aFilter[DLLK_FILTER_PREQ].pTxBuffer = NULL;
            ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                   DLLK_FILTER_PREQ, EDRV_FILTER_CHANGE_AUTO_RESPONSE);
            if (ret != kErrorOk)
                return ret;
#endif

            // update PRes
            ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES +
                                                (dllkInstance_g.curTxBufferOffsetCycle ^ 1)],
                                            newNmtState_p);
            if (ret != kErrorOk)
                return ret;

            ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES +
                                                dllkInstance_g.curTxBufferOffsetCycle],
                                            newNmtState_p);
            if (ret != kErrorOk)
                return ret;
            break;

        // no POWERLINK cycle -> normal ethernet communication
        case kNmtMsBasicEthernet:
        case kNmtCsBasicEthernet:
            // Fill Async Tx Buffer, because state BasicEthernet was entered
            ret = processFillTx(kDllAsyncReqPrioGeneric, newNmtState_p);
            if (ret != kErrorOk)
                return ret;
            break;

        default:
            return kErrorNmtInvalidState;
            break;

    }

    // update NMT state in instance structure. This is done after updating all
    // Tx frames, so no frame will be transmitted by callback function, when it
    // is not up to date yet.
    dllkInstance_g.nmtState = newNmtState_p;

    return ret;
}
示例#3
0
//------------------------------------------------------------------------------
tOplkError dllknode_setupLocalNode(tNmtState nmtState_p)
{
    tOplkError      ret = kErrorOk;
    UINT            handle;
    UINT            frameSize;
    UINT8           aMulticastMac[6];

#if !defined(CONFIG_INCLUDE_NMT_MN)
    UNUSED_PARAMETER(nmtState_p);
#endif

    // initialize flags for PRes and StatusRes (leave Flag 1 unchanged)
    dllkInstance_g.mnFlag1 = 0;
    dllkInstance_g.flag2 = 0;

#if defined(CONFIG_INCLUDE_NMT_MN)
    // initialize linked node list
    dllkInstance_g.pFirstNodeInfo = NULL;
    dllkInstance_g.pFirstPrcNodeInfo = NULL;
#endif
#if defined(CONFIG_INCLUDE_NMT_RMN)
    if (nmtState_p == kNmtRmsNotActive)
        dllkInstance_g.fRedundancy = TRUE;
    else
        dllkInstance_g.fRedundancy = FALSE;

    // AMNI
    if (dllkInstance_g.fRedundancy)
    {
        frameSize = C_DLL_MINSIZE_AMNI;
        ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypeAmni, kDllAsndNotDefined);
        if (ret != kErrorOk)
        {   // error occurred while registering Tx frame
            return ret;
        }
    }
#endif

    /*-----------------------------------------------------------------------*/
    /* register TxFrames in Edrv */
    // IdentResponse
    frameSize = C_DLL_MINSIZE_IDENTRES;
    ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypeAsnd, kDllAsndIdentResponse);
    if (ret != kErrorOk)
        return ret;

    // StatusResponse
    frameSize = C_DLL_MINSIZE_STATUSRES;
    ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypeAsnd, kDllAsndStatusResponse);
    if (ret != kErrorOk)
        return ret;

#if CONFIG_DLL_PRES_CHAINING_CN != FALSE
    // SyncResponse
    frameSize = C_DLL_MINSIZE_SYNCRES;
    ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypeAsnd, kDllAsndSyncResponse);
    if (ret != kErrorOk)
        return ret;
#endif

    // PRes
    if ((dllkInstance_g.dllConfigParam.fAsyncOnly == FALSE) &&
        (dllkInstance_g.dllConfigParam.presActPayloadLimit >= 36))
    {   // it is not configured as async-only CN,
        // so take part in isochronous phase and register PRes frame
        frameSize = dllkInstance_g.dllConfigParam.presActPayloadLimit + PLK_FRAME_OFFSET_PDO_PAYLOAD;
        ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypePres, kDllAsndNotDefined);
        if (ret != kErrorOk)
            return ret;

        // reset cycle counter
        dllkInstance_g.cycleCount = 0;
        dllkInstance_g.prescaleCycleCount = 0;
    }
    else
    {   // it is an async-only CN -> fool changeState() to think that PRes was not expected
        dllkInstance_g.cycleCount = 1;
    }

    // NMT request
    frameSize = C_IP_MAX_MTU;
    ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypeAsnd, kDllAsndNmtRequest);
    if (ret != kErrorOk)
        return ret;
    // mark Tx buffer as empty
    dllkInstance_g.aTxBufferStateNmtReq[0] = kDllkTxBufEmpty;
    dllkInstance_g.pTxBuffer[handle].txFrameSize = 0;
    dllkInstance_g.pTxBuffer[handle].pfnTxHandler = dllkframe_processTransmittedNmtReq;
    handle++;
    dllkInstance_g.aTxBufferStateNmtReq[1] = kDllkTxBufEmpty;
    dllkInstance_g.pTxBuffer[handle].txFrameSize = 0;
    dllkInstance_g.pTxBuffer[handle].pfnTxHandler = dllkframe_processTransmittedNmtReq;

    // non-POWERLINK frame
    frameSize = C_IP_MAX_MTU;
    ret = dllkframe_createTxFrame(&handle, &frameSize, kMsgTypeNonPowerlink, kDllAsndNotDefined);
    if (ret != kErrorOk)
        return ret;
    // mark Tx buffer as empty
    dllkInstance_g.aTxBufferStateNonPlk[0] = kDllkTxBufEmpty;
    dllkInstance_g.pTxBuffer[handle].txFrameSize = 0;
    dllkInstance_g.pTxBuffer[handle].pfnTxHandler = dllkframe_processTransmittedNonPlk;
    handle++;
    dllkInstance_g.aTxBufferStateNonPlk[1] = kDllkTxBufEmpty;
    dllkInstance_g.pTxBuffer[handle].txFrameSize = 0;
    dllkInstance_g.pTxBuffer[handle].pfnTxHandler = dllkframe_processTransmittedNonPlk;

    /*------------------------------------------------------------------------*/
    /* setup filter structure for Edrv */
    dllkfilter_setupFilters();

    // register multicast MACs in ethernet driver
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_SOC);
    ret = edrv_setRxMulticastMacAddr(aMulticastMac);
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_SOA);
    ret = edrv_setRxMulticastMacAddr(aMulticastMac);
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_PRES);
    ret = edrv_setRxMulticastMacAddr(aMulticastMac);
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_ASND);
    ret = edrv_setRxMulticastMacAddr(aMulticastMac);

#if defined(CONFIG_INCLUDE_NMT_RMN)
    if (dllkInstance_g.fRedundancy)
    {
        ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_AMNI);
        ret = edrv_setRxMulticastMacAddr(aMulticastMac);
    }
#endif

#if defined(CONFIG_INCLUDE_NMT_MN)
    if (NMT_IF_MN_OR_RMN(nmtState_p))
    {
        if ((ret = setupLocalNodeMn()) != kErrorOk)
            return ret;

#if defined(CONFIG_INCLUDE_NMT_RMN)
        if (nmtState_p == kNmtRmsNotActive)
        {
            if ((ret = setupLocalNodeCn()) != kErrorOk)
                return ret;
        }
#endif
    }
    else
    {
        if ((ret = setupLocalNodeCn()) != kErrorOk)
            return ret;
    }
#else
    if ((ret = setupLocalNodeCn()) != kErrorOk)
        return ret;
#endif

    // clear all asynchronous buffers
    ret = dllkcal_clearAsyncBuffer();
    if (ret != kErrorOk)
        return ret;

    // set filters in Edrv
    ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_COUNT, 0);

    return ret;
}
//------------------------------------------------------------------------------
tOplkError dllk_deleteNodeFilter(tDllkNodeInfo* pIntNodeInfo_p, tDllNodeOpType nodeOpType_p,
                                 BOOL fUpdateEdrv_p)
{
    tOplkError      ret = kErrorOk;
    BYTE            bPresFilterFlags = 0;

    switch (nodeOpType_p)
    {
        case kDllNodeOpTypeFilterPdo:
            bPresFilterFlags = DLLK_FILTER_FLAG_PDO;
            break;

        case kDllNodeOpTypeFilterHeartbeat:
            bPresFilterFlags = DLLK_FILTER_FLAG_HB;
            break;

        default:
            ret = kErrorDllInvalidParam;
            goto Exit;
    }

    pIntNodeInfo_p->presFilterFlags &= ~bPresFilterFlags;

    if (fUpdateEdrv_p != FALSE)
    {
        if ((pIntNodeInfo_p->presFilterFlags & (DLLK_FILTER_FLAG_PDO | DLLK_FILTER_FLAG_HB)) == 0)
        {
#if CONFIG_DLL_PRES_FILTER_COUNT < 0
            if (dllkInstance_g.usedPresFilterCount > 0)
                dllkInstance_g.usedPresFilterCount--;

            if (dllkInstance_g.usedPresFilterCount == 0)
            {
                // disable PRes Rx filter
                dllkInstance_g.aFilter[DLLK_FILTER_PRES].fEnable = FALSE;
                ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                       DLLK_FILTER_PRES, EDRV_FILTER_CHANGE_STATE);
                if (ret != kErrorOk)
                    goto Exit;
            }

#else
            UINT handle;

            for (handle = DLLK_FILTER_PRES; handle < DLLK_FILTER_COUNT; handle++)
            {
                if (ami_getUint8Le(&dllkInstance_g.aFilter[handle].aFilterValue[16]) ==
                                                pIntNodeInfo_p->nodeId)
                {
                    ami_setUint8Be(&dllkInstance_g.aFilter[handle].aFilterValue[16], C_ADR_INVALID);
                    dllkInstance_g.aFilter[handle].fEnable = FALSE;

                    ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                           handle, EDRV_FILTER_CHANGE_STATE);
                    if (ret != kErrorOk)
                        goto Exit;
                    break;
                }
            }
#endif
        }
    }
Exit:
    return ret;
}
示例#5
0
//------------------------------------------------------------------------------
tOplkError dllknode_cleanupLocalNode(tNmtState oldNmtState_p)
{
    tOplkError      ret = kErrorOk;
    BYTE            aMulticastMac[6];
#if NMT_MAX_NODE_ID > 0
    UINT            index;
#endif

#if defined(CONFIG_INCLUDE_NMT_MN)
    UINT            handle;
#else
    UNUSED_PARAMETER(oldNmtState_p);
#endif

    // remove all filters from Edrv
    ret = edrv_changeRxFilter(NULL, 0, 0, 0);

    // delete timer
#if CONFIG_TIMER_USE_HIGHRES != FALSE
    if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlCycle)) != kErrorOk)
        return ret;

#if defined(CONFIG_INCLUDE_NMT_RMN)
    if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlSwitchOver)) != kErrorOk)
        return ret;
#endif
#endif

#if defined(CONFIG_INCLUDE_NMT_MN)
    if ((ret = edrvcyclic_stopCycle(FALSE)) != kErrorOk)
        return ret;

    if ((ret = edrvcyclic_regSyncHandler(NULL)) != kErrorOk)
        return ret;
#endif

#if (CONFIG_DLL_PROCESS_SYNC == DLL_PROCESS_SYNC_ON_TIMER)
    if ((ret = synctimer_stopSync()) != kErrorOk)
        return ret;
#endif

#if defined(CONFIG_INCLUDE_NMT_MN)
    // destroy all data structures
    OPLK_FREE(dllkInstance_g.ppTxBufferList);
    dllkInstance_g.ppTxBufferList = NULL;
#endif

    // delete Tx frames
    if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_IDENTRES)) != kErrorOk)
        return ret;

    if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_STATUSRES)) != kErrorOk)
        return ret;

    if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_PRES)) != kErrorOk)
        return ret;

#if defined(CONFIG_INCLUDE_NMT_RMN)
    if (dllkInstance_g.fRedundancy)
    {
      if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_AMNI)) != kErrorOk)
        return ret;
    }
#endif

    dllkInstance_g.aTxBufferStateNmtReq[0] = kDllkTxBufEmpty;
    dllkInstance_g.aTxBufferStateNmtReq[1] = kDllkTxBufEmpty;
    if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_NMTREQ)) != kErrorOk)
        return ret;

#if CONFIG_DLL_PRES_CHAINING_CN != FALSE
    if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_SYNCRES)) != kErrorOk)
        return ret;
#endif

    dllkInstance_g.aTxBufferStateNonPlk[0] = kDllkTxBufEmpty;
    dllkInstance_g.aTxBufferStateNonPlk[1] = kDllkTxBufEmpty;
    if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_NONPLK)) != kErrorOk)
        return ret;

#if defined(CONFIG_INCLUDE_NMT_MN)
#if !defined(CONFIG_INCLUDE_NMT_RMN)
    if (NMT_IF_MN_OR_RMN(oldNmtState_p))
#else
    if (NMT_IF_MN_OR_RMN(oldNmtState_p) || (dllkInstance_g.fRedundancy))
#endif
    {   // local node was MN
        if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_SOC)) != kErrorOk)
            return ret;

        if ((ret = dllkframe_deleteTxFrame(DLLK_TXFRAME_SOA)) != kErrorOk)
            return ret;

        for (index = 0; index < tabentries (dllkInstance_g.aNodeInfo); index++)
        {
            if (dllkInstance_g.aNodeInfo[index].pPreqTxBuffer != NULL)
            {
                handle = (UINT)(dllkInstance_g.aNodeInfo[index].pPreqTxBuffer - dllkInstance_g.pTxBuffer);
                dllkInstance_g.aNodeInfo[index].pPreqTxBuffer = NULL;
                if (handle != DLLK_TXFRAME_PRES)
                {
                    if ((ret = dllkframe_deleteTxFrame(handle)) != kErrorOk)
                        return ret;
                }
            }
            // disable PReq and PRes for this node
            dllkInstance_g.aNodeInfo[index].preqPayloadLimit = 0;
            dllkInstance_g.aNodeInfo[index].presPayloadLimit = 0;
        }
    }
    else
    {   // local node was CN
        for (index = 0; index < tabentries(dllkInstance_g.aNodeInfo); index++)
        {
            // disable PReq and PRes for this node
            dllkInstance_g.aNodeInfo[index].presPayloadLimit = 0;
            dllkInstance_g.aNodeInfo[index].preqPayloadLimit = 0;
        }
    }
#else
    // must be CN, because MN part is not compiled!
#if NMT_MAX_NODE_ID > 0
    for (index = 0; index < tabentries(dllkInstance_g.aNodeInfo); index++)
    {
        // disable PRes for this node
        dllkInstance_g.aNodeInfo[index].presPayloadLimit = 0;
    }
#endif

#endif

    // de-register multicast MACs in Ethernet driver
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_SOC);
    ret = edrv_clearRxMulticastMacAddr(aMulticastMac);
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_SOA);
    ret = edrv_clearRxMulticastMacAddr(aMulticastMac);
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_PRES);
    ret = edrv_clearRxMulticastMacAddr(aMulticastMac);
    ami_setUint48Be(&aMulticastMac[0], C_DLL_MULTICAST_ASND);
    ret = edrv_clearRxMulticastMacAddr(aMulticastMac);

    return ret;
}