C 多设备板上的小型和大型终端访问-嵌入式软件体系结构

C 多设备板上的小型和大型终端访问-嵌入式软件体系结构,c,embedded-linux,endianness,vxworks,C,Embedded Linux,Endianness,Vxworks,我们有几个主板,可以把它们想象成主板。 这些主板包含微处理器、ASIC和FPGA的不同设备。。。 到目前为止,所有的设备都是基于16位Big-endian的。 目前的问题是,我们正在使用一种新的ASIC,它基于32个小端,而mobo上的所有其他设备都是大端。 我们已经创建了特定的API来读/写32位little endian。 在未来,我们可能会有mobo,它可以混合使用16/32大/小endian的设备。这些相同的设备可以用于不同的新的或旧的MOBO 我们使用嵌入式C(在Vxworks中)作为

我们有几个主板,可以把它们想象成主板。 这些主板包含微处理器、ASIC和FPGA的不同设备。。。 到目前为止,所有的设备都是基于16位Big-endian的。 目前的问题是,我们正在使用一种新的ASIC,它基于32个小端,而mobo上的所有其他设备都是大端。 我们已经创建了特定的API来读/写32位little endian。 在未来,我们可能会有mobo,它可以混合使用16/32大/小endian的设备。这些相同的设备可以用于不同的新的或旧的MOBO

我们使用嵌入式C(在Vxworks中)作为语言,我们的软件模块化,使用通用代码和mobo特定代码。 使用#定义和检查#ifdef的解决方案已经出现,但我不完全确定如何使用它们。 我们不能在处理器类型上真正使用#ifdef,因为相同的处理器可以在具有不同访问需求的不同mobo上使用


如果可能的话,我将非常感谢您在架构上和技术上对示例C代码示例的帮助。

为您的设备编写一个API

API将保证以微处理器的字节顺序接收来自微处理器的数据,并以微处理器的字节顺序将数据返回给微处理器。然后API进行LE->BE或任何转换

例如,至少您会有
asic\u read32
fpga\u read16
。您的
asic\u read32()
函数如下所示:

/* asic is little endian */
asic_read32(...)
    if microprocessor is big endian  /* do this at compile time with #if */
        le_data = read32_le(...)
        return to_big_endian(le_data)
    else
        return read32_le(...)
你的微处理器应用程序很高兴地忽略了这一切:

uin32_t num_bytes_frobbed = asic_read32(BYTES_FROBBED_REG);
printf("Frobbed %u bytes so far.\n", num_bytes_frobbed);
另外,对设备的所有访问都将通过一个API,因此,如果需要,您可以设置锁,以确保设备访问多线程安全


如果您对它感到满意并且它是合适的,那么如果您在系统上运行Linux,您可能能够抽象出设备本身并实现更高级别的功能,如
get\u frobbing\u statists(struct frobbing\u stats*stats)

,你可以使用系统提供的“EndiaNochange”函数:如果你不运行Linux,我会考虑为你的目标实现那些相同的函数(它们不是非常复杂的函数)。这不是转换函数的可用性或使用问题。问题在于如何知道何时使用这两种类型,因为mobo上的每个设备可能需要不同的endian访问。当数据是某种来自或将被读取的序列化流时,您只需担心正在访问的数据的endian性另一个装置。在这种情况下,根据流的规范,数据流应该始终是小端或大端(例如,TCP流始终是大端,也称为网络字节顺序)。然后,使用转换函数读取流的字段-如果数据已经与主机的字节顺序匹配,则该函数将变为不可操作。例如,如果数据流具有小的endian字段,则代码将使用
le32toh()读取32位字段
无论平台是big-endian还是little-endian。在一个小的endian平台上,该函数将是一个不可操作的函数,在一个大端ian平台上,该函数将交换字节。这个想法几乎是正确的,但op明确表示他不想使用预处理器。如果在系统初始化时检测到endianess,然后在*_read32()函数中使用运行时条件等,则效果会更好。