引言

在工业自动化与车载以太网融合场景中,FDCAN(Flexible Data-rate CAN)与 TSN(Time-Sensitive Networking)常共存于同一网关。FDCAN 提供确定性实时控制,TSN 则保证以太网流量调度。两者时间同步的精度直接决定系统协同性。STM32H7 系列以 480MHz Cortex-M7 内核、内置 FDCAN 控制器和 IEEE 1588 硬件时间戳单元,为硬件级抖动补偿提供了理想平台。

原理:时间同步与抖动来源

1. 同步机制

  • FDCAN 支持 CAN FD 协议,其时间戳单元(TSU)可捕获消息发送/接收的精确时刻,分辨率达 1ns(基于 480MHz 时钟)。
  • TSN 依赖 IEEE 802.1AS(gPTP),通过硬件时间戳在以太网 MAC 层打点,同步精度可达亚微秒。
  • 两者需共享统一时基(如系统时钟或外部 PPS),才能实现跨网络同步。

2. 抖动来源

  • 软件中断延迟:中断响应时间受缓存、分支预测影响,通常 100ns~1μs。
  • 总线仲裁延迟:FDCAN 多节点竞争时,消息发送时刻不确定。
  • 时钟漂移:晶振温漂导致时基偏差,需周期性校正。
  • 硬件路径差异:FDCAN 收发器、以太网 PHY 的传播延迟不同。

硬件级补偿的核心是:利用 STM32H7 的硬件时间戳在物理层捕获事件,避免软件介入,从而消除大部分抖动。

硬件架构与配置步骤

1. 时钟树配置

  • 使用 HSE 外部晶振(25MHz),通过 PLL1 倍频至 480MHz 系统时钟。
  • 配置 FDCAN 时钟源为 PLL2(如 80MHz),确保 TSU 计数频率与系统时钟独立,便于校准。
  • 使能 IEEE 1588 时间戳时钟(如 200MHz),用于以太网 MAC。

2. FDCAN 时间戳单元配置

  • 在 STM32CubeMX 中启用 FDCAN1,选择硬件时间戳模式。
  • 设置 TSU 为外部时钟输入(如 TIM1 的 TRGO),实现与 TSN 时基同步。
  • 配置消息 RAM 中的时间戳缓冲区,用于存储捕获时刻。

3. TSN 以太网配置

  • 使用 STM32H7 的 Ethernet MAC(支持 1588v2),启用硬件时间戳。
  • 配置 PTP 时钟源为系统时钟,并设置时钟校正寄存器。
  • 通过 MDIO 配置外部 PHY(如 KSZ9031)的 1588 功能。

4. 同步校准流程

  • 启动时,通过 GPIO 输出 PPS 信号,同时捕获 FDCAN 和 TSN 时间戳,计算初始偏移。
  • 周期(如 1s)通过 TSN 的 Sync 消息更新主时钟,并调整 FDCAN TSU 的补偿值。

代码实现

以下代码基于 STM32H743,使用 HAL 库,展示 FDCAN 时间戳捕获与 TSN 同步补偿的核心逻辑。

// FDCAN 时间戳捕获配置
void FDCAN_Timestamp_Init(void)
{
    FDCAN_HandleTypeDef hfdcan1;
    hfdcan1.Instance = FDCAN1;
    hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
    hfdcan1.Init.AutoRetransmission = DISABLE;
    hfdcan1.Init.TimestampConfig = FDCAN_TIMESTAMP_INTERNAL; // 使用内部 TSU
    hfdcan1.Init.TimestampPrescaler = 1; // 1ns 分辨率(480MHz)
    HAL_FDCAN_Init(&hfdcan1);

    // 配置 TSU 外部同步输入(如 TIM1_TRGO)
    HAL_FDCAN_EnableTimestampUnit(&hfdcan1, FDCAN_TIMESTAMP_UNIT_EXTERNAL);
}

// 捕获 FDCAN 消息时间戳(中断回调)
void HAL_FDCAN_RxFifo0MsgPendingCallback(FDCAN_HandleTypeDef *hfdcan)
{
    FDCAN_RxHeaderTypeDef rxHeader;
    uint8_t data[8];
    HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rxHeader, data);
    uint64_t fdcan_timestamp = rxHeader.Timestamp; // 硬件捕获时刻
    
    // 与 TSN 时钟比较,计算偏移
    uint64_t tsn_timestamp = Get_TSN_Time(); // 从以太网 PTP 获取
    int64_t offset = (int64_t)tsn_timestamp - (int64_t)fdcan_timestamp;
    
    // 补偿:调整 TSU 的偏移寄存器(假设有)
    HAL_FDCAN_SetTimestampOffset(&hfdcan1, offset);
}

// TSN 时钟读取(简化)
uint64_t Get_TSN_Time(void)
{
    // 读取以太网 MAC 的 1588 时间戳寄存器
    return (uint64_t)ETH->PTPTSHR << 32 | ETH->PTPTSLR;
}

抖动补偿算法

1. 静态补偿

  • 测量 FDCAN 收发器(如 TJA1044)的环路延迟(典型 200ns),在 TSU 中预设偏置。
  • 以太网 PHY 的延迟(如 150ns)在 MAC 时间戳中修正。

2. 动态补偿

  • 使用 PI 控制器:根据偏移量调整 TSU 的时钟频率(通过预分频器),实现闭环同步。
  • 示例:每收到一次 Sync 消息,计算偏移误差,更新预分频值。
// PI 控制器调整 TSU 预分频
void PI_Compensate(int64_t offset)
{
    static float integral = 0;
    float kp = 0.1, ki = 0.01;
    integral += offset * ki;
    int32_t adjust = (int32_t)(offset * kp + integral);
    // 限制调整范围
    if (adjust > 100) adjust = 100;
    if (adjust < -100) adjust = -100;
    HAL_FDCAN_SetTimestampPrescaler(&hfdcan1, 1 + adjust); // 调整计数频率
}

注意事项

  • 时钟源选择:FDCAN TSU 和 TSN 必须使用同一时基,否则无法同步。建议使用外部高精度时钟(如 OCXO)。
  • 中断优先级:FDCAN 时间戳中断应设为最高优先级,避免被其他中断延迟。
  • 消息 RAM 溢出:高频消息下,时间戳缓冲区可能溢出,需及时读取或使用 DMA。
  • 硬件版本:部分 STM32H7 型号的 TSU 不支持外部同步,需查阅数据手册(如 H743 支持,H750 可能受限)。
  • 调试技巧:通过 GPIO 输出同步脉冲,用示波器测量 FDCAN 和 TSN 的 PPS 信号,验证补偿效果。

总结

通过 STM32H7 的硬件时间戳单元,FDCAN 与 TSN 的同步抖动可从微秒级降至纳秒级。本文提供的配置与代码可作为基础框架,实际工程中需根据具体 PHY 和收发器调整延迟参数。硬件级补偿是嵌入式实时通信的基石,掌握后能显著提升系统确定性。