STM32H7 400MHz 下 FDCAN 与 TSN 时间同步的硬件触发对齐实践

1. 为什么需要硬件触发对齐?

在 TSN 网络中,时间同步由 gPTP(IEEE 802.1AS)协议维护,同步精度通常要求在亚微秒级。而 FDCAN(CAN FD)本身不具备硬件时间戳,仅依赖软件中断记录时间,会导致数百纳秒到微秒级的抖动。STM32H7 的 FDCAN 支持硬件时间戳(Timestamp)功能,但默认与系统时钟独立。若能将 FDCAN 的时基与 TSN 的全局时间(如通过外部 PHY 或交换机提供的 1PPS 信号)对齐,即可实现确定性通信。

硬件触发对齐的核心思想:利用 STM32H7 的 HRTIM(高分辨率定时器,分辨率 2.5ns @400MHz)或通用定时器,捕获外部 TSN 同步脉冲(如 1PPS),并产生触发事件,重置或校准 FDCAN 的时基计数器,使 FDCAN 时间戳与 TSN 全局时间同步。

2. 硬件架构与原理

2.1 信号链路

  • 外部 TSN 同步源:通常来自 TSN 交换机的 1PPS 输出(TTL 电平),或以太网 PHY 的 1PPS 信号。
  • STM32H7 输入捕获:将 1PPS 接入定时器输入捕获通道(如 TIM1_CH1),或 HRTIM 的外部事件输入。
  • FDCAN 时基:FDCAN 内核有一个 16 位自由运行计数器(FDCAN_TTTC),可配置为外部时钟源,并支持硬件复位/置位。

2.2 同步机制

  1. 捕获 1PPS 上升沿:定时器捕获当前计数值,并产生中断或 DMA 请求。
  2. 计算偏差:将捕获值与预期值(基于上一次同步周期)比较,得到时钟偏移。
  3. 硬件校准:通过定时器的比较输出(OC)或 HRTIM 的触发输出,连接到 FDCAN 的 TTTS(Time Triggered Transmit Schedule)输入,强制 FDCAN 时基重置为预设值。

这样,每个 1PPS 周期,FDCAN 时基被精确对齐到 TSN 全局时间,误差仅取决于硬件传播延迟(<10ns)。

3. 配置步骤(以 STM32H743 为例)

3.1 时钟配置

  • 系统时钟:400MHz(PLL1)。
  • 定时器时钟:TIM1 挂载在 APB2 上,频率为 400MHz(若 APB2 分频为 1)。
  • FDCAN 时钟:FDCAN 内核时钟可选 PCLK1(通常 100MHz)或 PLL2 输出,建议使用独立 PLL 以隔离抖动。

3.2 定时器配置(TIM1 输入捕获 + 输出比较)

// 初始化 TIM1 为输入捕获模式,捕获 1PPS 上升沿
TIM_HandleTypeDef htim1;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;  // 400MHz 计数
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 0xFFFFFFFF;  // 32位
HAL_TIM_IC_Init(&htim1);

// 配置通道1为输入捕获,上升沿触发
TIM_IC_InitTypeDef sConfigIC;
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_IC_SELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;  // 可增加滤波,但会增加延迟
HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);

3.3 FDCAN 时基配置

FDCAN 支持外部触发复位时基。在 STM32H7 中,FDCAN 的 TTTS 输入可连接到定时器比较输出。

// 使能 FDCAN 时间触发模式,并配置时基源
FDCAN_InitTypeDef hfdcan;
hfdcan.Instance = FDCAN1;
hfdcan.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan.NominalPrescaler = 2;  // 例如 100MHz -> 50MHz 时基
hfdcan.NominalTimeSeg1 = 13;
hfdcan.NominalTimeSeg2 = 2;
hfdcan.TTCM = FDCAN_TTCM_ENABLE;  // 使能时间触发模式
hfdcan.TTOCF = FDCAN_TTOCF_TTSE;  // 使能外部时间同步
HAL_FDCAN_Init(&hfdcan);

3.4 硬件触发连接

在 STM32H7 中,TIM1 的 OC1 输出可以映射到 FDCAN 的 TTTS 输入(通过 SYSCFG 或直接连接)。具体需查阅参考手册,通常使用 TIM1_CH1 的 OC 输出,配置为 PWM 模式,在捕获到 1PPS 后,延迟固定周期输出一个脉冲。

// 配置 TIM1 通道1为 PWM 模式,用于产生触发脉冲
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 100;  // 脉冲宽度,决定触发时刻
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);

3.5 中断处理与校准

在捕获中断中,计算偏差并调整 PWM 的脉冲宽度,以补偿时钟漂移。

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    static uint32_t last_capture = 0;
    uint32_t current_capture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
    uint32_t diff = current_capture - last_capture;
    last_capture = current_capture;
    
    // 期望周期为 1 秒(400MHz 计数),计算偏差
    int32_t error = (int32_t)diff - 400000000;
    // 调整 PWM 脉冲宽度,例如减小脉冲宽度提前触发
    __HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, 100 - error/1000);
}

4. 完整代码示例(简化)

// main.c 核心部分
int main(void)
{
    HAL_Init();
    SystemClock_Config();  // 400MHz
    MX_GPIO_Init();
    MX_TIM1_Init();
    MX_FDCAN1_Init();
    
    // 启动捕获和 PWM
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
    HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
    
    // 使能 FDCAN 并启动通信
    HAL_FDCAN_Start(&hfdcan1);
    HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
    
    while (1)
    {
        // 主循环处理其他任务
    }
}

5. 注意事项与优化

  • 硬件连接:确保 1PPS 信号电平兼容(3.3V),必要时加电平转换。
  • 滤波与延迟:输入捕获滤波器会增加延迟,建议在噪声可控时关闭或设置最小滤波。
  • FDCAN 时基分辨率:FDCAN 时基计数器频率不宜过高,否则 16 位计数器会快速溢出。建议配置为 1MHz~10MHz,并通过软件扩展。
  • 同步周期:1PPS 同步周期较长,中间漂移可能累积。可增加辅助同步(如每 10ms 同步一次)或使用更高频率的同步脉冲。
  • 抖动分析:使用逻辑分析仪测量实际触发时刻,确保误差在 ±50ns 内。若超出,检查中断响应时间,可改用 DMA 或硬件直接连接。
  • 多 FDCAN 同步:若使用多个 FDCAN,可共享同一触发信号,但需注意时基独立,需分别校准。

6. 总结

通过硬件触发对齐,STM32H7 的 FDCAN 能够与 TSN 网络实现亚微秒级同步,满足工业控制等高精度场景。本文的方法利用了定时器的捕获与比较功能,避免了软件中断的抖动,为异构网络融合提供了可靠方案。开发者可根据实际系统需求调整同步周期和校准算法,进一步优化性能。