Пример #1
0
//------------------------------------------------------------------------------
static BOOL processCnStateChange(tNmtState newNmtState_p, tOplkError* pRet_p)
{
    tOplkError          ret = kErrorOk;
    BOOL                fHandled = TRUE;
    UINT32              basicEthernetTimeout;
    tObdSize            obdSize;

    switch (newNmtState_p)
    {
        // node listens for POWERLINK frames and check timeout
        case kNmtCsNotActive:
            // create timer to switch automatically to BasicEthernet if no MN
            // is available in the network
            // read NMT_CNBasicEthernetTimeout_U32 from OD
            obdSize = sizeof(basicEthernetTimeout);
            ret = obd_readEntry(0x1F99, 0x00, &basicEthernetTimeout, &obdSize);
            if (ret != kErrorOk)
                break;

            if (basicEthernetTimeout != 0)
            {   // BasicEthernet is enabled
                ret = setupNmtTimerEvent(basicEthernetTimeout, kNmtEventTimerBasicEthernet);
                // potential error is forwarded to event queue which generates error event
            }
            break;

        // node processes only async frames
        case kNmtCsPreOperational1:
            break;

        // node processes isochronous and asynchronous frames
        case kNmtCsPreOperational2:
            ret = nmtu_postNmtEvent(kNmtEventEnterReadyToOperate);
            break;

        // node should be configured and application is ready
        case kNmtCsReadyToOperate:
            break;

        // normal work state
        case kNmtCsOperational:
            break;

        // node stopped by MN
        // -> only process asynchronous frames
        case kNmtCsStopped:
            break;

        // no POWERLINK cycle
        // -> normal ethernet communication
        case kNmtCsBasicEthernet:
            break;

        default:
            fHandled = FALSE;
            break;
    }
    *pRet_p = ret;
    return fHandled;
}
Пример #2
0
//------------------------------------------------------------------------------
static BOOL processMnStateChange(tNmtState newNmtState_p, tOplkError* pRet_p)
{
    tOplkError          ret = kErrorOk;
    BOOL                fHandled = TRUE;
    UINT32              waitTime;
    UINT32              startUp;
    tNmtEvent           timerEvent = kNmtEventTimerMsPreOp1;
    tObdSize            obdSize;

    switch (newNmtState_p)
    {
        // node listens for POWERLINK frames and check timeout
        case kNmtMsNotActive:
            // create timer to switch automatically to BasicEthernet/PreOp1 if no other MN active in network
            // check NMT_StartUp_U32.Bit13
            obdSize = sizeof(startUp);
            ret = obd_readEntry(0x1F80, 0x00, &startUp, &obdSize);
            if (ret != kErrorOk)
                break;

            if ((startUp & NMT_STARTUP_BASICETHERNET) != 0)
            {   // NMT_StartUp_U32.Bit13 == 1 -> new state BasicEthernet
                timerEvent = kNmtEventTimerBasicEthernet;
            }

        // intentional fall through
        case kNmtRmsNotActive:
            // read NMT_BootTime_REC.MNWaitNotAct_U32 from OD
            obdSize = sizeof(waitTime);
            ret = obd_readEntry(0x1F89, 0x01, &waitTime, &obdSize);
            if (ret != kErrorOk)
                break;

            ret = setupNmtTimerEvent(waitTime, timerEvent);
            // potential error is forwarded to event queue which generates error event
            break;

        // node processes only async frames
        case kNmtMsPreOperational1:
            // create timer to switch automatically to PreOp2 if MN identified all mandatory CNs

            // read NMT_BootTime_REC.MNWaitPreOp1_U32 from OD
            obdSize = sizeof(waitTime);
            ret = obd_readEntry(0x1F89, 0x03, &waitTime, &obdSize);
            if (ret != kErrorOk)
            {
                // ignore error, because this timeout is optional
                waitTime = 0;
            }
            if (waitTime == 0)
            {   // delay is deactivated, immediately post timer event
                ret = nmtu_postNmtEvent(kNmtEventTimerMsPreOp2);
            }
            else
            {
                ret = setupNmtTimerEvent(waitTime, kNmtEventTimerMsPreOp2);
            }
            // potential error is forwarded to event queue which generates error event
            break;

        // node processes isochronous and asynchronous frames
        case kNmtMsPreOperational2:
            break;

        // node should be configured and application is ready
        case kNmtMsReadyToOperate:
            break;

        // normal work state
        case kNmtMsOperational:
            break;

        // no POWERLINK cycle
        // -> normal ethernet communication
        case kNmtMsBasicEthernet:
            break;

        default:
            fHandled = FALSE;
            break;
    }
    *pRet_p = ret;
    return fHandled;
}
Пример #3
0
//------------------------------------------------------------------------------
static tOplkError configureDll(void)
{
    tOplkError      ret = kErrorOk;
    UINT32          nodeCfg;
    tObdSize        obdSize;
    tDllNodeInfo    dllNodeInfo;
    UINT            index;
    UINT8           count;

    // read number of nodes from object 0x1F81/0
    obdSize = sizeof(count);
    ret = obd_readEntry(0x1F81, 0, &count, &obdSize);
    if ((ret == kErrorObdIndexNotExist) || (ret == kErrorObdSubindexNotExist))
    {
        return kErrorOk;
    }
    else if (ret != kErrorOk)
    {
        return ret;
    }

    for (index = 1; index <= count; index++)
    {
        obdSize = sizeof(nodeCfg);
        ret = obd_readEntry(0x1F81, index, &nodeCfg, &obdSize);
        if (ret == kErrorObdSubindexNotExist)
        {   // not all subindexes of object 0x1F81 have to exist
            continue;
        }
        else if (ret != kErrorOk)
        {
            return ret;
        }

        if ((nodeCfg & (NMT_NODEASSIGN_NODE_EXISTS | NMT_NODEASSIGN_ASYNCONLY_NODE)) == NMT_NODEASSIGN_NODE_EXISTS)
        {   // node exists and runs in isochronous phase
            dllNodeInfo.nodeId = index;

            obdSize = sizeof(dllNodeInfo.presPayloadLimit);
            ret = obd_readEntry(0x1F8D, index, &dllNodeInfo.presPayloadLimit, &obdSize);
            if ((ret == kErrorObdIndexNotExist) || (ret == kErrorObdSubindexNotExist))
            {
                dllNodeInfo.presPayloadLimit = 0;
            }
            else if (ret != kErrorOk)
            {
                return ret;
            }

#if defined(CONFIG_INCLUDE_NMT_MN)
            if ((nodeCfg & (NMT_NODEASSIGN_NODE_IS_CN | NMT_NODEASSIGN_PRES_CHAINING)) == NMT_NODEASSIGN_NODE_IS_CN)
            {   // node is CN
                obdSize = sizeof(dllNodeInfo.preqPayloadLimit);
                ret = obd_readEntry(0x1F8B, index, &dllNodeInfo.preqPayloadLimit, &obdSize);
                if (ret != kErrorOk)
                    return ret;

                obdSize = sizeof(dllNodeInfo.presTimeoutNs);
                ret = obd_readEntry(0x1F92, index, &dllNodeInfo.presTimeoutNs, &obdSize);
                if (ret != kErrorOk)
                    return ret;
            }
            else
            {
                dllNodeInfo.presTimeoutNs = 0;
                dllNodeInfo.preqPayloadLimit = 0;
            }
#endif // if defined(INCLUDE_CONFIG_NMT_MN)

            ret = dllucal_configNode(&dllNodeInfo);
            if (ret != kErrorOk)
                return ret;
        }
    }

    return ret;
}
Пример #4
0
//------------------------------------------------------------------------------
static BOOL processGeneralStateChange(tNmtState newNmtState_p, tOplkError* pRet_p)
{
    tOplkError          ret = kErrorOk;
    UINT                nodeId;
    BOOL                fHandled = TRUE;
#if defined(CONFIG_INCLUDE_NMT_RMN)
    UINT32              startUp;
    tObdSize            obdSize;
#endif

    switch (newNmtState_p)
    {
        // POWERLINK stack is not running
        case kNmtGsOff:
            break;

        // first init of the hardware
        case kNmtGsInitialising:
            ret = nmtu_postNmtEvent(kNmtEventEnterResetApp);
            break;

        // init of the manufacturer-specific profile area and the
        // standardised device profile area
        case kNmtGsResetApplication:
            ret = nmtu_postNmtEvent(kNmtEventEnterResetCom);
            break;

        // init of the communication profile area
        case kNmtGsResetCommunication:
            ret = nmtu_postNmtEvent(kNmtEventEnterResetConfig);
            break;

        // build the configuration with infos from OD
        case kNmtGsResetConfiguration:
#if NMT_MAX_NODE_ID > 0
            // configure the DLL (PReq/PRes payload limits and PRes timeout)
            ret = configureDll();
            if (ret != kErrorOk)
            {
                break;
            }
#endif // NMT_MAX_NODE_ID > 0

#if defined(CONFIG_INCLUDE_NMT_RMN)
            obdSize = sizeof(startUp);
            ret = obd_readEntry(0x1F80, 0x00, &startUp, &obdSize);
            if (ret != kErrorOk)
                break;

            if ((startUp & NMT_STARTUP_REDUNDANCY) != 0)
            {   // NMT_StartUp_U32.Bit14 == 1
                ret = nmtu_postNmtEvent(kNmtEventEnterRmsNotActive);
                break;
            }
#endif
            // get node ID from OD
            nodeId = obd_getNodeId();
            //check node ID if not should be master or slave
            if (nodeId == C_ADR_MN_DEF_NODE_ID)
            {   // node shall be MN
#if defined(CONFIG_INCLUDE_NMT_MN)
                ret = nmtu_postNmtEvent(kNmtEventEnterMsNotActive);
#else
                DEBUG_LVL_ERROR_TRACE("processGeneralStateChange(): no MN functionality implemented\n");
#endif
            }
            else
            {   // node shall be CN
                ret = nmtu_postNmtEvent(kNmtEventEnterCsNotActive);
            }
            break;

        default:
            fHandled = FALSE;
            break;
    }

    *pRet_p = ret;
    return fHandled;
}
Пример #5
0
//------------------------------------------------------------------------------
tOplkError cfmu_processNodeEvent(UINT nodeId_p, tNmtNodeEvent nodeEvent_p, tNmtState nmtState_p)
{
    tOplkError          ret = kErrorOk;
    static UINT32       leSignature;
    tCfmNodeInfo*       pNodeInfo = NULL;
    tObdSize            obdSize;
    UINT32              expConfTime = 0;
    UINT32              expConfDate = 0;
    tIdentResponse*     pIdentResponse = NULL;
    BOOL                fDoUpdate = FALSE;
    BOOL                fDoNetConf = FALSE;

    if ((nodeEvent_p != kNmtNodeEventCheckConf) &&
        (nodeEvent_p != kNmtNodeEventUpdateConf) &&
        (nodeEvent_p != kNmtNodeEventFound) &&
        ((nodeEvent_p != kNmtNodeEventNmtState) || (nmtState_p != kNmtCsNotActive)))
        return ret;

    if ((pNodeInfo = allocNodeInfo(nodeId_p)) == NULL)
        return kErrorInvalidNodeId;

    if (pNodeInfo->cfmState != kCfmStateIdle)
    {
        // Send abort if SDO command is not undefined
        if (pNodeInfo->sdoComConHdl != UINT_MAX)
        {
            // Set node CFM state to an intermediate state to catch the SDO callback
            pNodeInfo->cfmState = kCfmStateInternalAbort;

            ret = sdocom_abortTransfer(pNodeInfo->sdoComConHdl, SDO_AC_DATA_NOT_TRANSF_DUE_LOCAL_CONTROL);
            if (ret != kErrorOk)
                return ret;

            // close connection
            ret = sdocom_undefineConnection(pNodeInfo->sdoComConHdl);
            pNodeInfo->sdoComConHdl = UINT_MAX;
            if (ret != kErrorOk)
            {
                DEBUG_LVL_CFM_TRACE("SDO Free Error!\n");
                return ret;
            }
        }

        // Set node CFM state to idle
        pNodeInfo->cfmState = kCfmStateIdle;
    }

    if ((nodeEvent_p == kNmtNodeEventFound) ||
        ((nodeEvent_p == kNmtNodeEventNmtState) && (nmtState_p == kNmtCsNotActive)))
    {   // just close SDO connection in case of IdentResponse or loss of connection
        return ret;
    }

    pNodeInfo->curDataSize = 0;

    // fetch pointer to ConciseDCF from object 0x1F22
    // (this allows the application to link its own memory to this object)
    pNodeInfo->pDataConciseDcf = (UINT8*)obd_getObjectDataPtr(0x1F22, nodeId_p);
    if (pNodeInfo->pDataConciseDcf == NULL)
        return kErrorCfmNoConfigData;

    obdSize = obd_getDataSize(0x1F22, nodeId_p);
    pNodeInfo->bytesRemaining = (UINT32)obdSize;
    pNodeInfo->eventCnProgress.totalNumberOfBytes = pNodeInfo->bytesRemaining;
#if (CONFIG_CFM_CONFIGURE_CYCLE_LENGTH != FALSE)
    pNodeInfo->eventCnProgress.totalNumberOfBytes += sizeof(UINT32);
#endif
    pNodeInfo->eventCnProgress.bytesDownloaded = 0;
    pNodeInfo->eventCnProgress.error = kErrorOk;
    if (obdSize < sizeof(UINT32))
    {
        pNodeInfo->eventCnProgress.error = kErrorCfmInvalidDcf;
        ret = callCbProgress(pNodeInfo);
        if (ret != kErrorOk)
            return ret;
        return pNodeInfo->eventCnProgress.error;
    }

    identu_getIdentResponse(nodeId_p, &pIdentResponse);
    if (pIdentResponse == NULL)
    {
        DEBUG_LVL_CFM_TRACE("CN%x Ident Response is NULL\n", nodeId_p);
        return kErrorInvalidNodeId;
    }

#if defined(CONFIG_INCLUDE_NMT_RMN)
    if (ami_getUint32Le(&pIdentResponse->featureFlagsLe) & PLK_FEATURE_CFM)
    {
        UINT subindex;

        // add size of network configuration (domains in CFM_ConciseDcfList_ADOM)
        for (subindex = 1; subindex <= NMT_MAX_NODE_ID; subindex++)
        {
            obdSize = obd_getDataSize(0x1F22, subindex);
            // Download only cDCFs with at least one entry
            if (obdSize > 4)
                pNodeInfo->eventCnProgress.totalNumberOfBytes += (UINT32)obdSize;
        }

        fDoNetConf = TRUE;
    }
#endif

    pNodeInfo->entriesRemaining = ami_getUint32Le(pNodeInfo->pDataConciseDcf);
    pNodeInfo->pDataConciseDcf += sizeof(UINT32);
    pNodeInfo->bytesRemaining -= sizeof(UINT32);
    pNodeInfo->eventCnProgress.bytesDownloaded += sizeof(UINT32);

    if (pNodeInfo->entriesRemaining == 0)
    {
        pNodeInfo->eventCnProgress.error = kErrorCfmNoConfigData;
        ret = callCbProgress(pNodeInfo);
        if (ret != kErrorOk)
            return ret;
    }
    else if (nodeEvent_p == kNmtNodeEventUpdateConf)
        fDoUpdate = TRUE;
    else
    {
        obdSize = sizeof(expConfDate);
        ret = obd_readEntry(0x1F26, nodeId_p, &expConfDate, &obdSize);
        if (ret != kErrorOk)
        {
            DEBUG_LVL_CFM_TRACE("CN%x Error Reading 0x1F26 returns 0x%X\n", nodeId_p, ret);
        }
        obdSize = sizeof(expConfTime);
        ret = obd_readEntry(0x1F27, nodeId_p, &expConfTime, &obdSize);
        if (ret != kErrorOk)
        {
            DEBUG_LVL_CFM_TRACE("CN%x Error Reading 0x1F27 returns 0x%X\n", nodeId_p, ret);
        }

        if ((expConfDate != 0) || (expConfTime != 0))
        {   // expected configuration date or time is set
            if ((ami_getUint32Le(&pIdentResponse->verifyConfigurationDateLe) != expConfDate) ||
                (ami_getUint32Le(&pIdentResponse->verifyConfigurationTimeLe) != expConfTime))
            {   // update configuration because date or time differ from the expected value
                fDoUpdate = TRUE;
            }
            // store configuration in CN at the end of the download
            pNodeInfo->fDoStore = TRUE;
            pNodeInfo->eventCnProgress.totalNumberOfBytes += sizeof(UINT32);
        }
        else
        {   // expected configuration date and time is not set
            fDoUpdate = TRUE;
            // do not store configuration in CN at the end of the download
            pNodeInfo->fDoStore = FALSE;
        }
    }

#if (CONFIG_CFM_CONFIGURE_CYCLE_LENGTH != FALSE)
    obdSize = sizeof(cfmInstance_g.leCycleLength);
    ret = obd_readEntryToLe(0x1006, 0x00, &cfmInstance_g.leCycleLength, &obdSize);
    if (ret != kErrorOk)
    {   // local OD access failed
        DEBUG_LVL_CFM_TRACE("Local OBD read failed %d\n", ret);
        return ret;
    }
#endif

    if ((fDoUpdate == FALSE) &&
        !(fDoNetConf && (pNodeInfo->entriesRemaining == 0)))
    {
        pNodeInfo->cfmState = kCfmStateIdle;

        // current version is already available on the CN, no need to write new values, we can continue
        DEBUG_LVL_CFM_TRACE("CN%x - Cfg Upto Date\n", nodeId_p);

        ret = downloadCycleLength(pNodeInfo);
        if (ret == kErrorReject)
        {
            pNodeInfo->cfmState = kCfmStateUpToDate;
        }
    }
    else if (nodeEvent_p == kNmtNodeEventUpdateConf)
    {
        pNodeInfo->cfmState = kCfmStateDownload;
        ret = downloadObject(pNodeInfo);
        if (ret == kErrorOk)
        {   // SDO transfer started
            ret = kErrorReject;
        }
    }
    else
    {
        pNodeInfo->cfmState = kCfmStateWaitRestore;

#if defined(CONFIG_INCLUDE_NMT_RMN)
        if (pNodeInfo->entriesRemaining == 0)
        {
            DEBUG_LVL_CFM_TRACE("CN%x - CFM Network-Cfg Update. Restoring Default...\n");
        }
        else
#endif
        {
            DEBUG_LVL_CFM_TRACE("CN%x - Cfg Mismatch | MN Expects: %lx-%lx ", nodeId_p, expConfDate, expConfTime);
            DEBUG_LVL_CFM_TRACE("CN Has: %lx-%lx. Restoring Default...\n",
                                 ami_getUint32Le(&pIdentResponse->verifyConfigurationDateLe),
                                 ami_getUint32Le(&pIdentResponse->verifyConfigurationTimeLe));
        }

        //Restore Default Parameters
        pNodeInfo->eventCnProgress.totalNumberOfBytes += sizeof(leSignature);
        ami_setUint32Le(&leSignature, 0x64616F6C);

        pNodeInfo->eventCnProgress.objectIndex = 0x1011;
        pNodeInfo->eventCnProgress.objectSubIndex = 0x01;
        ret = sdoWriteObject(pNodeInfo, &leSignature, sizeof(leSignature));
        if (ret == kErrorOk)
        {   // SDO transfer started
            ret = kErrorReject;
        }
        else
        {
            // error occurred
            DEBUG_LVL_CFM_TRACE("CfmCbEvent(Node): sdoWriteObject() returned 0x%02X\n", ret);
        }
    }
    return ret;
}