//------------------------------------------------------------------------------
tOplkError edrvcyclic_startCycle(void)
{
    tOplkError ret = kErrorOk;

    if (edrvcyclicInstance_l.cycleTimeUs == 0)
    {
        ret = kErrorEdrvInvalidCycleLen;
        goto Exit;
    }

    // clear Tx buffer list
    edrvcyclicInstance_l.curTxBufferList = 0;
    edrvcyclicInstance_l.curTxBufferEntry = 0;
    OPLK_MEMSET(edrvcyclicInstance_l.ppTxBufferList, 0,
                sizeof(*edrvcyclicInstance_l.ppTxBufferList) * edrvcyclicInstance_l.maxTxBufferCount * 2);

    ret = hrestimer_modifyTimer(&edrvcyclicInstance_l.timerHdlCycle,
                                edrvcyclicInstance_l.cycleTimeUs * 1000ULL,
                                timerHdlCycleCb, 0L, TRUE);

#if (EDRV_USE_TTTX == TRUE)
    edrvcyclicInstance_l.fNextCycleValid = FALSE;
#endif

#if CONFIG_EDRV_CYCLIC_USE_DIAGNOSTICS != FALSE
    edrvcyclicInstance_l.lastSlotTimeStamp = 0;
#endif

Exit:
    return ret;
}
Ejemplo n.º 2
0
//------------------------------------------------------------------------------
static tOplkError processStartReducedCycle(void)
{
    tOplkError      ret = kErrorOk;

    // start the reduced cycle by programming the cycle timer
    // it is issued by NMT MN module, when PreOp1 is entered

    // clear the asynchronous queues
    ret = dllkcal_clearAsyncQueues();

    // reset cycle counter (every time a SoA is triggered in PreOp1 the counter is incremented
    // and when it reaches C_DLL_PREOP1_START_CYCLES the SoA may contain invitations)
    dllkInstance_g.cycleCount = 0;

    // remove any CN from isochronous phase
    while (dllkInstance_g.pFirstNodeInfo != NULL)
    {
        ret = dllknode_deleteNodeIsochronous(dllkInstance_g.pFirstNodeInfo);
        if (ret != kErrorOk)
            goto Exit;
    }

    while (dllkInstance_g.pFirstPrcNodeInfo != NULL)
    {
        ret = dllknode_deleteNodeIsochronous(dllkInstance_g.pFirstPrcNodeInfo);
        if (ret != kErrorOk)
            goto Exit;
    }

    // change state to NonCyclic,
    // hence changeState() will not ignore the next call
    dllkInstance_g.dllState = kDllMsNonCyclic;

#if CONFIG_TIMER_USE_HIGHRES != FALSE
    if (dllkInstance_g.dllConfigParam.asyncSlotTimeout != 0)
    {
        ret = hrestimer_modifyTimer(&dllkInstance_g.timerHdlCycle,
                                    dllkInstance_g.dllConfigParam.asyncSlotTimeout,
                                    dllkframe_cbMnTimerCycle, 0L, FALSE);
    }
#endif

    dllkInstance_g.curLastSoaReq = 0;
    dllkInstance_g.curTxBufferOffsetCycle = 0;

Exit:
    return ret;
}
//------------------------------------------------------------------------------
static tOplkError processTxBufferList(void)
{
    tOplkError          ret = kErrorOk;
    tEdrvTxBuffer*      pTxBuffer = NULL;
#if (EDRV_USE_TTTX == TRUE)
    BOOL                fFirstPacket = TRUE;
    UINT64              launchTime;
    UINT64              cycleMin;
    UINT64              cycleMax;
    UINT64              currentMacTime = 0;
#endif

#if (EDRV_USE_TTTX == TRUE)
    edrv_getMacTime(&currentMacTime);
    if (!edrvcyclicInstance_l.fNextCycleValid)
    {
        edrvcyclicInstance_l.nextCycleTime = currentMacTime + EDRV_SHIFT;
        launchTime = edrvcyclicInstance_l.nextCycleTime;
        edrvcyclicInstance_l.fNextCycleValid = TRUE;
    }
    else
    {
        launchTime = edrvcyclicInstance_l.nextCycleTime;
        if (currentMacTime > launchTime)
        {
            ret = kErrorEdrvTxListNotFinishedYet;
            goto Exit;
        }
    }

    cycleMin = launchTime;
    cycleMax = launchTime + (edrvcyclicInstance_l.cycleTimeUs * 1000ULL);

    while ((pTxBuffer = edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferEntry]) != NULL)
    {
        if (pTxBuffer == NULL)
        {
            ret = kErrorEdrvBufNotExisting;
            goto Exit;
        }

        if (fFirstPacket)
        {
            pTxBuffer->launchTime = launchTime ;
            fFirstPacket = FALSE;
        }
        else
        {
            launchTime = launchTime + (UINT64)pTxBuffer->timeOffsetNs;
            pTxBuffer->launchTime = launchTime;
        }

        if ((pTxBuffer->launchTime - cycleMin) >  (cycleMax - cycleMin))
        {
            ret = kErrorEdrvTxListNotFinishedYet;
            goto Exit;
        }

        ret = edrv_sendTxBuffer(pTxBuffer);
        if (ret != kErrorOk)
            goto Exit;

        pTxBuffer->launchTime = 0;
        edrvcyclicInstance_l.curTxBufferEntry++;
    }

#else

    while ((pTxBuffer = edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferEntry]) != NULL)
    {
        if (pTxBuffer->timeOffsetNs == 0)
        {
            ret = edrv_sendTxBuffer(pTxBuffer);
            if (ret != kErrorOk)
            {
                goto Exit;
            }
        }
        else
        {
            ret = hrestimer_modifyTimer(&edrvcyclicInstance_l.timerHdlSlot,
                                        pTxBuffer->timeOffsetNs,
                                        timerHdlSlotCb,
                                        0L,
                                        FALSE);

            break;
        }

        edrvcyclicInstance_l.curTxBufferEntry++;
    }
#endif

Exit:
    if (ret != kErrorOk)
    {
        if (edrvcyclicInstance_l.pfnErrorCb != NULL)
        {
            ret = edrvcyclicInstance_l.pfnErrorCb(ret, pTxBuffer);
        }
    }
    return ret;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
//------------------------------------------------------------------------------
tOplkError dllk_cbCyclicError(tOplkError errorCode_p, tEdrvTxBuffer* pTxBuffer_p)
{
    tOplkError      ret = kErrorOk;
    tNmtState       nmtState;
    UINT            handle = 0;
    UINT32          arg;
    tEventDllError  dllEvent;

    TGT_DLLK_DECLARE_FLAGS;

    UNUSED_PARAMETER(pTxBuffer_p);

    TGT_DLLK_ENTER_CRITICAL_SECTION();

    nmtState = dllkInstance_g.nmtState;
    if (!NMT_IF_MN(nmtState))
    {
#if defined(CONFIG_INCLUDE_NMT_RMN)
        if (errorCode_p == kErrorEdrvCurTxListEmpty)
        {
            switch (dllkInstance_g.nmtEventGoToStandby)
            {
                case kNmtEventGoToStandby:
                    hrestimer_modifyTimer(&dllkInstance_g.timerHdlSwitchOver,
                                          (dllkInstance_g.dllConfigParam.switchOverTimeMn -
                                           dllkInstance_g.dllConfigParam.cycleLen) * 1000ULL,
                                          dllk_cbTimerSwitchOver, 0L, FALSE);
                    dllkInstance_g.nmtEventGoToStandby = kNmtEventNoEvent;
                    break;

                case kNmtEventGoToStandbyDelayed:
                    hrestimer_modifyTimer(&dllkInstance_g.timerHdlSwitchOver,
                                          (dllkInstance_g.dllConfigParam.delayedSwitchOverTimeMn -
                                           dllkInstance_g.dllConfigParam.cycleLen)  * 1000ULL,
                                          dllk_cbTimerSwitchOver, 0L, FALSE);
                    dllkInstance_g.nmtEventGoToStandby = kNmtEventNoEvent;
                    break;

                default:
                    break;
            }
        }
#endif
        // ignore errors if not MN
        goto Exit;
    }

    if (pTxBuffer_p != NULL)
    {
        handle = (UINT)(pTxBuffer_p - dllkInstance_g.pTxBuffer);
    }

    BENCHMARK_MOD_02_TOGGLE(7);

    switch (errorCode_p)
    {
        case kErrorEdrvCurTxListEmpty:
        case kErrorEdrvTxListNotFinishedYet:
        case kErrorEdrvNoFreeTxDesc:
            dllEvent.dllErrorEvents = DLL_ERR_MN_CYCTIMEEXCEED;
            dllEvent.nodeId = handle;
            dllEvent.nmtState = nmtState;
            dllEvent.oplkError = errorCode_p;
            ret = errhndk_postError(&dllEvent);
            break;

        default:
            arg = dllkInstance_g.dllState | (handle << 16);
            // Error event for API layer
            ret = eventk_postError(kEventSourceDllk, errorCode_p, sizeof(arg), &arg);
            break;
    }

Exit:
    TGT_DLLK_LEAVE_CRITICAL_SECTION();

    return ret;
}