【问题标题】:Embedded systems : data size management (64bits host sending data to a 32bits device)嵌入式系统:数据大小管理(64 位主机向 32 位设备发送数据)
【发布时间】:2021-09-14 10:02:27
【问题描述】:

我正在构建一个 32 位 嵌入式设备,外部参与者可以通过 PKCS#11 接口与之通信。

基本上有3个组件:

  • 我们的嵌入式设备(仅支持 32 位)
  • 主机(可能是 32 位或 64 位,不由我决定)
  • 宿主库(可以编译成 32 位或 64 位)

我正在开发设备和主机库,我现在的主要问题是确保与 32 位和 64 位主机应用程序的兼容性。

pkcs11t.h 将 CK_ULONG 定义为:

/* an unsigned value, at least 32 bits long */
typedef unsigned long int CK_ULONG;

问题是long int 的大小在主机(8 字节)和我们的设备(4 字节)上不会相同。

我很想使用uint32_t 而不是unsigned long int。但the standard 声明如下:

因此,许多数据和指针类型会因环境而异(例如,CK_ULONG 有时是 32 位,有时可能是 64 位)。但是,这些细节不应该影响应用程序,假设它是使用与应用程序链接到的 Cryptoki 库一致的 Cryptoki 头文件编译的。

主机将向嵌入式设备发送请求,假设主机发送请求 ID 为0。嵌入式设备如何知道它是 32 位还是 64 位值?

所以我的问题如下:在 32 位嵌入式设备中处理 64 位数据类型的最佳方法是什么?我正在考虑在主人的图书馆里做类似的事情:

CK_ULONG data = 0x42; // user input, could be anything

#ifdef HOST_64
assert(data <= 4294967295);
#endif

send_data_to_device((uint32_t)data);

但是感觉不对……

【问题讨论】:

  • 您的环境似乎定义了适当的数据类型。为什么要改变一些东西?
  • 我没有得到显示的代码目的。在哪种情况下,您希望 0x42 的值无法断言小于或等于更高的值?您是否打算以某种方式在那里使用sizeof()
  • 这不是重复的,但那里的帖子可能会帮助您从其他角度看待您的问题。 stackoverflow.com/questions/46442411/…
  • what's the best way to handle 64 bits data types in a 32 bits embedded device? 不?你想具体处理什么?有什么可以“处理”的? to ensure compatibility with both 32 and 64 bits host applications 标准 PKCS#11 就是为此而设计的。 ULONG 是“至少 32 位长”,不完全是 32 位长,标准知道这一点。你为什么在乎?
  • 我编辑了我的帖子以(希望)更清晰。我关心这一点,因为当主机向我的嵌入式设备(比如 ULONG)发送一些数据时,我不知道我应该读取 4 字节还是 8 字节,因为嵌入式设备不知道主机是 64 位还是 32 位

标签: c embedded pkcs#11


【解决方案1】:

这里没有真正的问题。 您的嵌入式系统仅支持 32 位值。 您将使用某些指定的链接在系统之间进行通信,我确信这些链接已经定义,例如TCP/IP、RS232等

无论传输层是什么,您都需要定义一个协议来打包您在两个系统之间传输的数据。

此协议应处理数据大小,还应考虑较大数据类型的数据打包与各个 CPU 的字节顺序之间的任何差异。

例如,您可能认为 32 位值在内存中被打包为 [byte1][byte2][byte3][byte4],但实际上它可能被其中一个处理器处理为 [byte3][byte4][byte1][byte2],这意味着您必须主动将数据打包到一个协议中指定的约定格式,而不仅仅是从内存中复制数据。

如果您的 32 位系统必须支持 64 位值,那么您将需要为它编写自己的处理程序 - 即使将 64 位值解包为两个 32 位值,例如 64bit_value -> 32bit_value_high_bytes + 32bit_value_low_bytes。

您的 64 位系统可以继续支持 64 位,尽管您希望在传输到 32 位系统之前解析的任何值都应根据您的协议进行转换。

如果您提供库代码来执行协议处理,那么我建议所有库函数调用都返回错误消息值。

因此您可以在 64 位系统上使用:

if(send_data_to_device(data) != RESULT_SUCCESS)
{
   // some error handling
}

您的库代码可能是:

int send_data_to_device(ULONG data)
{
    #ifdef HOST_64
       if(data > 4294967295) return RESULT_VALUE_OUT_OF_BOUNDS;
    #endif
    // preform data transport

   return RESULT_SUCCESS;
}

注意事项:

  • 小心将 64 位值转换为 32 位值作为 正符号 64 位值可以给出负符号 32 位值。

  • 不要依赖使用结构和联合在实时数据和打包数据之间切换。

【讨论】:

    【解决方案2】:

    大概您的嵌入式设备执行一项服务。该服务需要一个接口。

    您需要指定该接口。每个可用的命令、值、操作等都应与可接受的值范围以及错误条件下发生的情况一起记录。然后你只需在两边都实现规范。

    任何一方的位深度或数据类型都无关紧要。如果数据不符合接口要求,则必须在使用接口前进行转换。

    【讨论】:

      猜你喜欢
      • 2018-11-14
      • 2013-12-17
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 1970-01-01
      • 1970-01-01
      • 2010-09-13
      相关资源
      最近更新 更多