15 Time Synchronization
15.1 What is Time Synchronization?
时间同步是自适应平台基础中的一个功能集群。时间同步通过库向应用程序提供C++ API,该库作为RTA-VRTE入门套件的一部分提供,并与应用程序链接以访问该功能。
本版本包含非常少量的时间同步文档。因此,本章不完整或不正确,将在下一版本中扩展。
15.2 Responsibilities
在自适应平台中,时间同步功能集群支持通过事件的时间协调在多个目标ECU之间分配功能。
协调可以包括跟踪事件(及时)和同时触发不同目标ECU上的事件。
时间同步建立一个或多个时基资源,这些时基资源形成使用标准化网络协议gPTP(Generalized Precision Time Protocol)与其他目标ECU同步的主或从时间参考。自适应应用程序使用所提供的C++ API访问时基资源,从而可以协调它们的活动。
15.3 Operation
同步网络由一个时间主机和一个或多个时间从机组成。
时间主机使用标准化的时间分配协议将全局时基分配给从机。Time Slave使用接收到的时间值来更新和维护其自己的本地时间,然后自适应应用程序可以通过时间同步API使用该本地时间。
一个系统可以由多个Time Master节点组成——每个节点都为一个独立同步的网络提供服务。此外,时间网关节点可以被配置为在一个时间分配网络上充当从节点,在第二个网络上充当主节点,从而转发同步时间。
15.3.1 Generalized Precision Time Protocol
AUTOSAR时间同步使用通用精确时间协议(gPTP)来同步时间主机和时间从机之间的时钟。
gPTP包括四条消息:
1.从主设备到从设备的同步请求,请求从设备进行同步。
- 2.从主ECU到从ECU的后续消息,包含主ECU上的时间戳。
- 3.从从属设备到主设备的延迟请求,请求主设备发送响应。
- 4.从主设备到从设备的延迟响应消息。
最初,主时钟和从时钟是不同步的,这意味着这两个时钟之间没有关系。
主设备的初始同步消息由从设备接收
从设备只是使用其本地尚未同步的时钟记录接收时间(t2)。
主控台的后续消息包含使用主控台时钟记录的同步消息的传输时间(t1)。
在从设备接收时,记录的传输时间(主时钟)和接收时间(从时钟)可由从设备上的时间同步使用,以确定两个时钟之间的差异🔺C,从而执行初始同步。
在同步/后续消息之后,两个时钟的差异仅在于消息从主设备传输到从设备所花费的时间;
消息的传播延迟(🔺P)。
t4 不等于 t5
t4 = t5 + 🔺P .
为了测量这种传播延迟,从设备发送一个延迟请求,它将自己时钟上的时间记为t6。
当主设备接收到消息时,它将其时钟记为t7,然后将其发送给从设备,从设备现在可以使用t6和t7中的差来计算延迟。
因为Slave的时钟已经落后于在先前同步期间引入的传播时间P,所以t6和t7之间的差实际上是2🔺P,因为在发送延迟请求时引入了另一个🔺P。
总时间🔺C+🔺P通过考虑消息传播时间延迟以及初始时钟差,使从时钟能够与主时钟精确同步。然而随着时间的推移,主时钟和从时钟会自然地漂移。为了避免漂移变得重要,协议包括定期重新同步,以确保主时钟和从时钟保持同步。
如果你看不懂上面的介绍,也可以看下面的图片介绍 gPTP
这样就完成了ECU1与ECU2的时间同步。
15.4 Implementation
如前所述,在分布式系统中关联不同事件时,不同自适应应用程序和/或ECU之间的时间同步至关重要,以便能够及时跟踪此类事件或在准确的时间点触发它们。因此,AUTOSAR为自适应应用程序提供了时间同步API,以便它们可以检索与其他ECU同步的时间信息。此API由TSync客户端库librb-TSync.so实现,该库必须与任何想要使用同步时间的应用程序链接。
15.4.1 rb-tsyncd
RTA-VRTE入门套件还包括一个TSync提供程序守护程序rb-tsyncd。这是一个守护进程,它根据配置文件创建SynchronizedTimeBaseProvider,并使用当前硬件时间更新这些时基。
当使用-c命令行选项启动提供程序守护程序时,会指定适当的JSON配置文件。TSync提供程序包中包含一个示例配置文件。请注意,一旦TSync守护进程使用FlatCFG获取其配置,-c选项最终将被删除。
15.4.1.1 Configuration
在此版本中,rb-tsyncd不使用FlatCFG来获取配置值。可以使用JSON配置文件启动TSync守护进程,该配置文件允许设置时基列表。
时基有一个名称和一个与其关联的类型字符串(该类型将在本版本中被读取但被忽略)。
时基名称由TSync提供程序用于创建用于保存时基数据的共享内存对象。
该共享内存对象将由库使用,并且可以在初始化时间同步期间创建TsyncIdentifierMap时使用配置文件中提供的名称进行访问(更多信息请参阅第15.5.1节)。
{
"timebases":[
{"name" : "/sysclock", "type" : "dummy"},
{"name" : "/sysclock2", "type" : "also a dummy"}
]
}
15.4.2 Virtual Local Time
为了同步两个或多个ECU的时间,有必要改变每个ECU上的时间。然而,ECU上的硬件时钟是只读的,因此时间同步引入了虚拟本地时间,其功能类似于硬件时钟,但增加了轻松更改时间的能力。每个时基都有自己关联的虚拟本地时间。目前,虚拟本地时间必须手动递增。
15.5 Working with Time Synchronization
15.5.1 Initialization
第一步是在时基和SynchronizedTimeBaseConsumer或SynchronizedTime BaseProvider之间建立映射。
在其他软件集群中,AUTOSAR通常会使用端口原型在ISOLAR VRTE中建立这样的映射,但当前的实现在代码中使用显式的TsyncIdentifierMap:
static constexpr uint32_t TB_ID = 42;
static constexpr const char* INSTANCE_SPECIFIER_STR ="/tsync";
static TsyncIdentifierMap time_base_mappings =
{
{ TB_ID, INSTANCE_SPECIFIER_STR }
};
使用实例指定器时要小心:有些方法要求实例指定器的前缀为“/”。
实例化的映射随后由InitializeTimeBaseResource使用。
设置时基资源后,必须使用tsync_Open初始化tsync ptp库:
最后,可以使用TSync_OpenTimeBase函数创建时基:
InitializeTimeBaseResources(time_base_mappings);
TSync_ReturnType ret = TSync_Open();
if(ret != E_OK)
{
return EXIT_FAILURE;
}
TSync_TimeBaseHandleType timebase = TSync_OpenTimebase(TB_ID);
if(timebase == TSYNC_INVALID_HANDLE)
{
return EXIT_FAILURE;
}
15.5.2 Creating a SynchronizedTimeBaseConsumer
必须先构造InstanceSpecifier,然后才能生成使用者。在之前创建TsyncIdentifierMap时,我们使用了“/<实例说明符>”,但在这种情况下,不需要前导“/”来创建InstanceSpecifier。
auto data = time_base_mappings[TB_ID].data();
Result<InstanceSpecifier> rs = InstanceSpecifier::Create(data + 1);
// skip theleading ’/’
if (!rs.HasValue())
{
return EXIT_FAILURE;
}
SynchronizedTimeBaseConsumer现在可以使用此InstanceSpecifier构建:
SynchronizedTimeBaseConsumer consumer(rs.Value());
And the time can be retrieved with the GetCurrentTime method:
并且可以使用GetCurrentTime方法检索时间:
Timestamp ts = consumer.GetCurrentTime();
15.5.3增加虚拟本地时间
时基的虚拟本地时间可以使用TSync_GetCurrentVirtualLocalTime函数检索。这是通过传入您希望获得虚拟本地时间的时基和指向先前初始化的TSync_VirtualLocalTimeStamp的指针来完成的,该指针将用当前虚拟本地时间更新:
TSync_ReturnType rs = TSync_GetCurrentVirtualLocalTime(timebase, &local_time);
if(rs != E_OK)
{
return EXIT_FAILURE;
}
必须使用TSync_TimeStampType手动递增时间,如下所示:
timestamp.seconds++;
if(!timestamp.seconds)
{
// The lower part of the timestamp overflowed
// so increment the upper part
timestamp.secondsHi++;
}
然后可以使用TSync_BusSetGlobalTime函数设置时基的时间。
在本例中,我们不需要提供TSync_UserDataType或TSync_MeasurementType,因此使用nullptr。
rs = TSync_BusSetGlobalTime(timebase,
×tamp,
nullptr,
nullptr,
&local_time);
if(rs != E_OK)
{
return EXIT_FAILURE;
}
15.6 AUTOSAR API
15.6.1 SynchronizedTimeBaseProvider
Name ara::tsync::SynchronizedTimeBaseProvider
Entity Type Class
Header ara/tsync/synchronized_time_base_provider.h
Methods SetTime
UpdateTime
GetCurrentTime
SetRateCorrection
GetRateDeviation
GetUserData
GetUserData
RegisterTimeValidationNotification
UnregisterTimeValidationNotification
Description Adaptive Application provision of a synchronized timebase. Class methods
provide the current time_point, the rate deviation, the current status
and the received user data (if any).
The class constructor takes an InstanceSpecifier that references a Port-
Prototype.