[车载以太网] SOME/IP 参数和数据结构的序列化

  • 本篇系对以太网SOME/IP协议的参数数据结构的序列化/反序列化的解读。

概述:SOME/IP 参数和数据结构的序列化

大小端/字节序

  • 每个参数(parameter)的字节顺序由接口定义进行规定。

  • 所有的 SOME/IP Header 字段,应该以网络字节序(大端)编码。

PRS_SOME/IP_00368

  • Payload中参数的字节顺序由配置决定。

PRS_SPME/IP_00026

参数和数据结构的序列化

  • 序列化Serialization)是指将数据结构对象状态 转换为**二进制串(字节数组)**的过程。

SOME/IP协议 在传输过程中也自然需要进行序列化反序列化

  • SOME/IP 需要基于通信接口规范定义的参数列表进行序列化。

接口规范明确了PDU协议数据单元 )中所有数据结构的精确位置,并且在设计时必须考虑存储器对齐的问题。

  • 对齐操作 通过在数据项之后添加填充元素来【调整数据的起始位置】,以确保数据从特定的、对齐的内存地址开始。

这是因为在某些处理器架构中,当数据从某个数的倍数(例如32位的倍数)地址开始时,数据访问会更加高效。

  • 如果可变大小数据不是序列化数据流中的最后一个元素,则:应该通过在可变大小数据后面插入填充元素来实现数据的对齐。

PRS_SOMEIP_00611 / RS_SOMEIP_00028 , RS_SOMEIP_00029

  • 请注意,Padding 值未被定义。

Member2: 以 UInt8 元素组成的一维可变长数组 / Member5: 以 UInt8 元素组成的一维可变长数组

Member2: 以 UInt8 元素组成的一维可变长数组 / Member5: 以 UInt8 元素组成的一维可变长数组

  • 对齐应该能总是被计算出,从 SOME/IP 报文的起始处。

  • 固定长度数据元素后面不得有填充元素,以确保后面数据的对齐。

如果定长数据元素后面的数据被填充,则这必须被显式地考虑进数据类型定义中。

  • 可变长度数据元素后面的数据对齐应为8、16、32、64、128或256位。

RS_SOMEIP_000028 / RS_SOMEIP_000029

基本数据类型

  • 应支持以下基本数据类型:
Type Description Size [bit] Remark
boolean TRUE/FALSE value 8 FALSE (0), TRUE (1)
uint8 unsigned Integer 8
uint16 unsigned Integer 16
uint32 unsigned Integer 32
sint8 signed Integer 8
sint16 signed Integer 16
sint32 signed Integer 32
float32 floating point number 32 IEEE 754 binary32 (Single Precision)
float64 floating point number 64 IEEE 754 binary64 (Double Precision)
  • 每个参数的字节顺序由接口定义进行规定。

结构化数据类型 (结构体)

  • 结构体的序列化 应尽可能接近内存布局

这意味着参数 应按顺序序列化缓冲区 中。

对于结构体来说,特别要考虑正确的内存对齐

如果需要对齐,请在接口定义中插入保留/填充元素,因为SOME/IP实现不会自动添加此类填充。

  • SOME/IP实现不应自动插入虚拟/填充元素。

  • 如果SOME/IP实现遇到导致PDU未正确对齐的接口规范(例如,由于未对齐的结构体),SOME/IP实现应在发现不对齐的结构体 时发出警告,但不应在生成代码时失败

  • 结构体的序列化应按照规范精确地进行。

  • 可以在结构体前面添加一个8位、16位或32位的【可选】的【长度字段】,其取决于接口规范的配置。

如果未指定长度字段的长度,则必须假定长度为0,并且消息中没有长度字段。

  • 结构体的长度字段 描述了结构体的字节数

如果长度大于接口定义中指定的结构体长度,则只有接口规范中指定的字节将被解释,其他字节将根据长度字段被跳过。

这样可以实现可扩展的结构体,从而更好地实现接口的迁移。

  • 如果长度效于所有结构体成员的长度之和,且接收者无法在本地提供缺失数据的替换时,则 反序列化应被中止,且该报文应被视为是畸形的。

  • 结构体的序列化应遵循结构化的数据类型的【深度优先遍历】。

字符串

如下需求是定长字符串和动态长度字符串的共同点

  • PRS_SOMEIP_00372\] 不同的Unicode字符集编码应被支持,包括: UTF-8 / UTF-16BE / UTF-16LE

  • PRS_SOMEIP_00948\] UTF-8 字符串应以 `\0` 字符 结束。

RS_SOMEIP_00038

  • PRS_SOMEIP_00084\] UTF-16LE 和 UTF-16BE 字符串应以"`\0`"字符结尾。这意味着它们应以(至少)两个`0x00`字节结束

  • PRS_SOMEIP_00086\] 应忽略UTF-16LE和UTF-16BE有一个奇数长度的最后一个字节将被忽略。

BOM应包含在固定长度字符串和动态长度字符串中。
BOM允许检测所使用的编码。

固定长度的字符串

  • PRS_SOMEIP_00760\] 固定长度的字符串可以以可选的【长度字段】开头。 PRS_SOMEIP_00760

  • PRS_SOMEIP_00373\] 尽管字符串长度固定,但应以"`\0`"字符结尾

动态长度的字符串

  • PRS_SOMEIP_00089\] 动态长度的字符串应以长度字段开头。(强制要求)

  • PRS_SOMEIP_00090\] **长度字段**放置在BOM之前,BOM包含在长度中

  • 注意,字符串的最大字节数 (包括以"\0"结尾)也应从数据类型定义中得出。
  • PRS_SOMEIP_00092\] : 对于 \[PRS_SOMEIP_00084\], \[PRS_SOMEIP_00085\] 和 \[PRS_SOMEIP_00086\] 条款,也适用于具有动态长度的字符串

  • PRS_SOMEIP_00094\] 如果未配置该字段,则添加在字符串前面的长度字段的长度为32位(长度字段的默认长度)。

数组

固定长度的数组

  • 固定长度数组更容易在非常小的设备中使用。使用动态长度数组的ECU可能需要更多资源。

  • PRS_SOMEIP_00944\] 固定长度的数组可以以可选的长度字段开头

一维数组

  • PRS_SOMEIP_00099\] 具有固定长度"`n`"的一维数组应恰好包含相同类型的"`n`"个元素。可选的长度字段可以位于第1个元素之前

PRS_SOMEIP_00099\]的布局如图4.7所示。

多维数组

  • PRS_SOMEIP_00101\] 多维数组的序列化遵循C/C++编程语言中多维数组的内存布局(以行为主的顺序 / row-major order)

动态长度的数组

  • PRS_SOMEIP_00375\] 具有动态长度的数组布局应基于固定长度数组的布局

  • PRS_SOMEIP_00107\] 动态长度数组应具有长度为8、16或32位的长度字段。这应由配置决定

如果长度字段的长度设置为0位,则数组中的元素数量必须固定;因此,此时是固定长度的数组。 (参考图 4.9 / 4.10)

  • 在一维数组中,使用一个长度字段,该字段携带用于数组的字节数。
  • 静态长度元素的数量,可以很容易地通过除以元素的大小来计算。
  • 在动态长度元素的情况下,无法直接计算元素的数量,必须按顺序解析元素。

图4.10显示了动态长度多维数组的结构。

  • PRS_SOMEIP_00114

  • 在多维数组中,每个不同维度的子数组都应有自己的长度字段。
  • 如果需要静态缓冲区大小分配,数据类型定义应定义每个维度的最大长度。
  • 理由:在以字节为单位测量长度时,可以在反序列化中跳过复杂的多维数组。
  • SOME/IP还支持同一维度中列的不同长度和行的不同长度。见图4.10中的k_1和k_2。每个动态长度数组前面都需要有一个长度指示器。这适用于外部和所有内部/嵌套数组。
  • PRS_SOMEIP_00945\] 如果未配置,则添加在动态长度数组前面的长度字段的长度为32位(长度字段的默认长度)。

  • PRS_SOMEIP_00705\] 在SOME/IP中不考虑枚举。枚举应作为无符号整数数据类型传输

  • PRS_SOMEIP_00300\] 位字段应作为无符号数据类型uint8/uint16/uint32/uint64传输。

Union / Variant

Y 推荐文献

https://www.autosar.org/fileadmin/standards/R24-11/FO/AUTOSAR_FO_PRS_SOMEIPProtocol.pdf

https://www.autosar.org/fileadmin/standards/R19-11/FO/AUTOSAR_RS_SOMEIPProtocol.pdf

X 参考文献