4. 非同步节点启动

任务说明

在一个已有节点完成冷启动并进入同步运行的FlexRay网络中,需要新增一个节点(非同步启动节点)。该节点不参与冷启动,而是在网络运行期间上电,通过接收同步帧完成时钟同步并加入通信。本案例要求配置该节点的同步参数,使其能够正确同步到全局网络时间并正常收发数据。

同步原理与关键参数

非同步节点启动时,首先进入协议启动状态机中的“等待同步帧”状态。节点通过监听通道上的同步帧(来自已同步的同步节点),收集足够的同步帧对后,计算时钟校正值并应用,从而完成时间同步。关键参数包括:

  • pAllowHaltDueToClockSyncFault:设为0,允许节点在同步失败时继续尝试,而非直接停止。
  • pClusterDriftDamping:设为1,启用漂移阻尼,加快同步收敛。
  • pDecodingCorrection:设为1,启用解码校正,补偿接收路径延迟。
  • pDelayCompensationA/B:对应通道A/B的延迟补偿值,需根据实际总线长度设置。
  • pKeySlotId:设为0,表示该节点不发送同步帧(非同步节点)。
  • pKeySlotUsedForStartup:设为0,不参与冷启动。
  • pKeySlotUsedForSync:设为0,不作为同步节点。
  • pLatestTx:配置为允许发送数据帧的时隙。

代码实现

以下配置基于EB tresos生成的FlexRay驱动,展示非同步节点的核心参数设置。代码中省略了与同步无关的通信参数,聚焦于同步相关配置。

/* FlexRay非同步节点配置 - 基于EB tresos FlexRay驱动 */
#include "FlexRay.h"
#include "FlexRay_Internal.h"

/* 全局时间同步参数结构 */
const FlexRay_TimeSyncParamsType FlexRay_TimeSyncParams = {
    .pAllowHaltDueToClockSyncFault = 0u,   /* 同步故障时不允许停止 */
    .pClusterDriftDamping          = 1u,   /* 启用漂移阻尼 */
    .pDecodingCorrection           = 1u,   /* 启用解码校正 */
    .pDelayCompensationA           = 2u,   /* A通道延迟补偿,单位: 微时隙(MT) */
    .pDelayCompensationB           = 2u,   /* B通道延迟补偿 */
    .pOffsetCorrectionStart        = 1599u,/* 偏移校正起始点,位于周期末尾 */
    .pOffsetCorrectionOut          = 1599u,/* 偏移校正输出点 */
    .pRateCorrectionOut            = 1599u,/* 速率校正输出点 */
    .pRateCorrectionStart          = 1599u,/* 速率校正起始点 */
    .pSyncFrameTable               = 0u,   /* 不使用外部同步帧表 */
    .pSynchronizationFrameFilter   = 0u    /* 不启用同步帧过滤 */
};

/* 节点配置 - 非同步节点 */
const FlexRay_NodeConfigType FlexRay_NodeConfig = {
    .pNodeId            = 4u,              /* 节点ID,用于调试 */
    .pClusterParams     = &FlexRay_ClusterParams,
    .pTimeSyncParams    = &FlexRay_TimeSyncParams,
    .pKeySlotId         = 0u,              /* 关键时隙ID=0,非同步节点 */
    .pKeySlotUsedForStartup = 0u,          /* 不参与冷启动 */
    .pKeySlotUsedForSync    = 0u,          /* 不作为同步节点 */
    .pKeySlotOnlyEnabled    = 0u,          /* 允许发送数据帧 */
    .pChannelA            = 1u,            /* 启用A通道 */
    .pChannelB            = 1u,            /* 启用B通道 */
    .pSingleSlotEnabled   = 0u,            /* 允许动态段发送 */
    .pAllowHaltDueToClockSyncFault = 0u,   /* 同步故障时继续运行 */
    .pMaxWithoutClockCorrectionFatal = 0u, /* 不启用致命同步丢失检测 */
    .pMaxWithoutClockCorrectionPassive = 0u /* 不启用被动同步丢失检测 */
};

/* 初始化函数 - 在系统启动时调用 */
void FlexRay_NonSyncNode_Init(void)
{
    /* 设置节点为非同步模式 */
    FlexRay_GlobalConfig.pNodeConfig = &FlexRay_NodeConfig;
    
    /* 配置通信周期长度,与网络中已有节点一致 */
    FlexRay_GlobalConfig.pMacroticksPerCycle = 3200u;  /* 通信周期=3200MT */
    FlexRay_GlobalConfig.pMicroticksPerMacrotick = 4u; /* 1MT=4uT */
    
    /* 配置静态段时隙,与网络一致 */
    FlexRay_GlobalConfig.pStaticSlotDuration = 40u;    /* 静态时隙=40MT */
    FlexRay_GlobalConfig.pNumberOfStaticSlots = 40u;   /* 40个静态时隙 */
    
    /* 配置同步帧期望接收的时隙(来自同步节点) */
    FlexRay_GlobalConfig.pExpectedSyncFrameSlots[0] = 1u;  /* 同步节点1在时隙1 */
    FlexRay_GlobalConfig.pExpectedSyncFrameSlots[1] = 2u;  /* 同步节点2在时隙2 */
    FlexRay_GlobalConfig.pExpectedSyncFrameCount = 2u;     /* 期望2个同步帧 */
    
    /* 初始化硬件 */
    FlexRay_InitController(&FlexRay_GlobalConfig);
}

/* 启动非同步节点 */
void FlexRay_NonSyncNode_Start(void)
{
    /* 进入就绪状态,等待网络同步 */
    FlexRay_ControllerEnterReadyState();
    
    /* 启动协议引擎,开始监听同步帧 */
    FlexRay_ControllerStartCommunication();
    
    /* 等待同步完成,通过中断或轮询检查 */
    /* 同步完成后,FlexRay_GetGlobalTime()将返回有效的全局时间 */
}

/* 主循环中的同步状态检查 */
uint8_t FlexRay_NonSyncNode_CheckSyncStatus(void)
{
    FlexRay_SyncStatusType syncStatus;
    
    syncStatus = FlexRay_GetSyncStatus();
    
    if (syncStatus == FLEXRAY_SYNC_STATUS_SYNCED) {
        /* 已同步到全局时间 */
        return 1u;
    } else if (syncStatus == FLEXRAY_SYNC_STATUS_PENDING) {
        /* 正在同步中 */
        return 0u;
    } else {
        /* 同步失败 */
        return 2u;
    }
}

同步状态机

就绪 等待同步帧 (收集同步帧对) 同步计算 (校正时钟) 已同步 启动 收到≥2个 同步帧对 校正完成 同步丢失(连续N个周期未收到有效同步帧) 超时/故障 正常状态 异常路径

落地与验证

集成步骤:

  1. 将上述配置代码集成到基于EB tresos生成的FlexRay驱动中,替换默认的同步参数。
  2. 确保网络中的同步节点(时隙1和2)已正常运行,通信周期为3200MT。
  3. 编译并烧录到目标节点,节点上电后调用FlexRay_NonSyncNode_Init()和FlexRay_NonSyncNode_Start()。

验证方法:

  1. 使用FlexRay总线分析仪(如Vector CANoe)监控总线流量,观察节点是否在启动后约2~3个通信周期内完成同步。
  2. 调用FlexRay_NonSyncNode_CheckSyncStatus(),返回值应为1(已同步)。
  3. 读取全局时间寄存器,与同步节点的全局时间差值应小于一个宏节拍(1MT=4μs@80Mbps)。
  4. 在静态时隙中发送数据帧,确认其他节点能正确接收。

判定标准:节点上电后5个通信周期内完成同步,全局时间偏差≤1MT,且数据通信正常,即视为通过。