DCD域内时钟同步策略

背景

车机在正式环境(车上)采用 TBOX 作为唯一时间来源,来保证 DCD 域内所有时间统一。

大部分开发人员不需要也没有 TBOX, 但是部分应用以及网络请求需要相对正确的世界时间。

QNX 内 TimeSyncService 接受外域(TBOX) 的时间,并和 Android / MCU 等模块做时间同步功能。

当前策略

使用(Android) NTP 开关来做正式环境和开发环境的行为控制。

图来源(2.3 问题:时间同步,上电前20秒,QNX和安卓的时间对不上)

📷 [图片: DCD域内时钟同步策略架构图 — 左侧 MCU (Time Task、Unix to UTC、Ext RTC);中间 QNX (Vehicle Core、TimeSyncService、SystemClock);右侧 Android (QacService、TimeSynchronizer);底部 Eth Driver (EMAC) 与 Eth PHY 88Q2220。TimeSyncService 同时与 MCU、Android 双向同步]

  • ENABLE NTP

    Android 在开发环境中,会从 NTP 获取正确时间,并反向同步给 QNX TimeSyncService, QNX TimeSyncService 负责同步其他域(MCU)内的时间 。

  • DISABLE NTP

    正式环境(车上)中, QNX TimeSyncService 只接受外域的时间,并将该时间同步给其他模块。

    Android 只接受 1577836800000L (2020/01/01 08:00:00) 之后的时间。

不同版本时间同步差异

主线

时序图

NTP ENABLE

📷 [图片: Q/A 时间同步时序图 (NTP ENABLE 主线) — QNX_TimeSyncService 周期发送时间给 Android_TimeSynchronizer;后者检查 QNX 来源时间有效性(1577836800000L 之前为无效)及时间差变化(同 elapsedRealtimeDiff 内视为相同);时间差与上次相同时 DO NOTHING,不同时检查 3s 内是否收到过不同请求,有效且 3s 内有过则在第 3s 再确认 NTP,否则请求 NTP;请求成功后若与 QNX 时间不同则反向同步给 QNX_TimeSyncService]

PlantUml Code
@startuml
 
title Q/A时间同步时序图
 
participant QNX_TimeSyncService
participant Android_TimeSynchronizer
participant NTPServer
 
note over QNX_TimeSyncService: 周期发送时间
QNX_TimeSyncService->Android_TimeSynchronizer: 发送时间
 
note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
Android_TimeSynchronizer->Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
alt 时间差与上次发送的相同
    note over Android_TimeSynchronizer: DO NOTHING
else 时间差与上次发送的不同
    note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
    Android_TimeSynchronizer->Android_TimeSynchronizer: 检查 3s 内是否收到过不同的请求
    alt 时间有效且 3s 内收到过不同的请求
        note over Android_TimeSynchronizer: 3s 内已经收到过不同的请求,在第3S时刻再确认 NTP
    else 时间无效或 3s 内未收到过不同的请求(新请求)
        note over Android_TimeSynchronizer: 请求 NTP 时间()
    end
end
 
== Request NTP Phase ==
 
note over Android_TimeSynchronizer: 请求 NTP 时间()
    Android_TimeSynchronizer->NTPServer: 请求 NTP 时间
note over NTPServer: 处理请求
alt 请求失败
    note over Android_TimeSynchronizer: DO NOTHING
else 请求成功
    NTPServer->Android_TimeSynchronizer: 返回 NTP 时间
    note over Android_TimeSynchronizer: 反向同步 NTP 时间
    alt NTP 时间与 QNX_TimeSyncService 时间不同
        Android_TimeSynchronizer->QNX_TimeSyncService: 发送 NTP 时间
    else NTP 时间与 QNX_TimeSyncService 时间相同
        note over Android_TimeSynchronizer: DO NOTHING
    end
end
 
@enduml

时间有效性规则:认为 1577836800000L (2020/01/01 08:00:00) 之前的时间无效。

时间差检查:例如上次收到 20:00、这次收到 20:01,则检查 Math.abs(1min - elapsedRealtimeDiff) < 50MS,若 20:01 在 1min 时刻收到则相同,反之亦然。

NTP DISABLE

参考 E4 时序图(注:原文档此处自引用,实际指向当前文档自身,可能为原文笔误)

相关提交

E4

  • 使用 AndroidSystemProperty:: ro.build.micar_enable_ntp 作为 NTP 开关(开=true, 关=false)

时序图

📷 [图片: Q/A 时间同步时序图 (E4 版本) — 与主线类似;当时间无效或时间差与上次相同时 DO NOTHING;时间有效且时间差不同时检查 3s 内是否收到过不同请求,3s 内有过则第 3s 再确认 NTP,新请求则立即请求 NTP;成功后若与 QNX 时间不同则反向同步给 QNX_TimeSyncService]

PlantUml Code

@startuml
 
title Q/A时间同步时序图
 
participant QNX_TimeSyncService
participant Android_TimeSynchronizer
participant NTPServer
 
note over QNX_TimeSyncService: 周期发送时间
QNX_TimeSyncService->Android_TimeSynchronizer: 发送时间
 
note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
Android_TimeSynchronizer->Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
alt 时间无效或时间差与上次发送的相同
    note over Android_TimeSynchronizer: DO NOTHING
else 时间有效且时间差与上次发送的不同
    note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
    Android_TimeSynchronizer->Android_TimeSynchronizer: 检查 3s 内是否收到过不同的请求
    alt 3s 内收到过不同的请求
        note over Android_TimeSynchronizer: 3s 内已经收到过不同的请求,在第3S时刻再确认 NTP
    else 3s 内未收到过不同的请求(新请求)
        note over Android_TimeSynchronizer: 请求 NTP 时间()
    end
end
 
== Request NTP Phase ==
 
note over Android_TimeSynchronizer: 请求 NTP 时间()
    Android_TimeSynchronizer->NTPServer: 请求 NTP 时间
note over NTPServer: 处理请求
alt 请求失败
    note over Android_TimeSynchronizer: DO NOTHING
else 请求成功
    NTPServer->Android_TimeSynchronizer: 返回 NTP 时间
    note over Android_TimeSynchronizer: 反向同步 NTP 时间
    alt NTP 时间与 QNX_TimeSyncService 时间不同
        Android_TimeSynchronizer->QNX_TimeSyncService: 发送 NTP 时间
    else NTP 时间与 QNX_TimeSyncService 时间相同
        note over Android_TimeSynchronizer: DO NOTHING
    end
end
 
@enduml

E3

  • 使用 AndroidSystemProperty:: ro.build.micar_debug_build 作为 NTP 开关(开=true, 关=false)

TODO

当前 TimeSynchronizer 是在 CarController(com.mi.car.controller) 进程内, 是一个 Java 进程,开机后会有一段时间内, Q/A 的时间不同步, 可以更改至 VHAL 内实现部分功能。

相关链接