• chapter7——处理字节顺序


    1.定义

    字节顺序定义数据在计算机系统中的存储格式。它描述存储器中地址的最高有效位(MSB)和最低有效位(LSB)的位置。对于数据始终以32位形式保存在系统存储器中的真正32位系统,字节顺序没什么实际意义,但是对于要将字节或16位半字映射到系统存储器中32位字的系统,字节顺序不匹配就会影响数据完整性。

    字节顺序结构有两种类型,大端模式(Big Endian, BE)和小端模式(Little Endian, LE)。大端模式将MSB保存在最低存储器地址处,小端模式将LSB保存在最低存储器地址处。多字节数据的最低存储器可以认为是数据的起始地址。
    下表是分别按大端模式和小端模式保存在存储器中的32位十六进制数0xAABBCCDD。字节0表示最低存储器地址。

    在这里插入图片描述

    在按原生数据类型(如32位)引用数据时,两种字节顺序所存储的多字节数据域是相同的。但在按字节或半字类型访问数据时,字域次序与系统的字节顺序配置相关。

    在以半字方式处理时,存储器地址必须是2的倍数。

    2.小端模式和大端模式的比较

    • 在小端模式中,因为最低位字节偏移值为0,并首先访问,访问1、2、4或更长字节数的汇编语言指令能按同样方式处理所有格式。同样,由于地址偏移量和字节数之间1:1的关系(偏移0对应字节0),多精度的数学程序也相对容易编写。
    • 在大端模式中,因为先访问高阶字节,所以很容易通过查看偏移量为0的字节来判断数值的正负。所以无须接收所有字节包就能知道符号信息。由于数字同时也以其打印出来的次序保存,所以对从二进制转化为十进制的程序特别有效。

    大多数嵌入式通信处理器和定制解决方案在数据层采用大端模式(PowerPC,SPARC等)。因为为这些处理器所写的老程序通常遵循网络字节顺序(大端模式)。

    某些CPU可以通过设置处理器寄存器而在大端或小端模式(双字节顺序)间切换。

    3.处理字节顺序不匹配的问题

    • 在单个系统中字节顺序不会产生什么问题。只有在两台电脑通信时它才会产生影响。每个处理器和每种通信协议必须选择一种字节顺序。因此,如果需要通过存储器通信,两种不同字节顺序类型的处理器就会产生冲突。类似地,小端模式处理器在试图访问大端模式网络时需要用软件对字节重新排序。如果计算机无意间从共享存储区域或文件中读取以相反格式写入的二进制数据时,字节顺序的差异就会导致问题。
    • 另一个字节顺序会导致问题的领域是网络通信。由于在同一网络中可能存在不同类型(大端模式或小端模式)的处理器,它们之间必须彼此通信。因此网络协议栈和通信协议也必须定义字节顺序。否则,不同字节顺序的两个节点可能无法通信。
      在实际应用中,TCP/IP族中的所有协议层都定义为大端模式。也就是说,各层头中的16或32位值(如IP地址、包长度或校验和)必须首先发送或接收最高有效字节。TCP/IP协议所使用的多字节整数表达方式有时称为网络字节顺序。即使各终端计算机都是小端模式的,它们之间所传输的数据必须在通过网络前先转化为网络字节顺序,然后在接收端再转化为小端模式。

    4.访问32位存储器

    • 字节地址和32位数据总线上特定位的关系如下所示:
      在这里插入图片描述
    • 下表为按8位、16位和32位访问大端与小端模式系统时的数据字节映射。
      在这里插入图片描述
      在这里插入图片描述

    5.处理字节顺序不匹配

    在包含若干IP的SOC中必然会发生字节顺序不匹配的问题,几乎所有第三方公司的IP都支持与处理器同样的字节顺序类型。处理字节顺序不匹配问题的最简单方法是为系统选择一种字节顺序类型(即,小端模式或大端模式),并将全部其他不同字节顺序的模块转化为目标字节顺序类型。

    典型的字节顺序类型由系统中CPU体系结构的实现决定,所以建议目标的字节顺序类型与处理器的字节顺序类型相匹配。在对第三方IP选型时要考虑的另一个因素是确认其是否支持双字节顺序结构,以使IP可以方便地编程为大端模式或小端模式以与系统无缝集成。

    有两种连接相反字节顺序外设的方法。根据应用的需要,要么选择将地址保持稳定(在地址不变处字节保持在同一地址)或者将位顺序保持稳定(在数据不变处地址改变)。

    • 保持数据完整性(数据不变)

    由于不同的字节顺序模式下多字节域具有不同的字节地址,因此,如果将多字节域作为单个条目进行操作,那么当其在各IP之间移动时,必须保留该条目的位次序。

    对于跨字节边界的多位域也同样如此。比如,一个含16位控制寄存器编程模型的IP。如果控制寄存器位域 [8:7] 定义了控制域,那么要求对于所有访问控制寄存器的操作,要保持该16位之间的稳定关系,而不再与字节顺序有关。

    为了理解匹配字节顺序以使数据位顺序完整的过程,以由小端模式的外设接收连续帧并将接收到的数据通过DMA/CPU保存到系统存储器举例。
    在这里插入图片描述
    接收到的连续帧以Type、H2、H1和H0的顺序保存在外设存储器中。帧中的域可能跨多个字节并不在字节边界处终止,例如状态域可能是12位。所以对于应用程序来说,数据不会因为字节顺序转换而改变就显得很重要,因为这样软件就可以以该顺序处理数据了。

    在这里插入图片描述
    在上图中,数据按小端寻址保存在外设的存储器中。现在当数据要传送到大端模式的系统RAM中时,必须保证数据位顺序保持不变。为了用硬件达到这个目的,需要对访问外设RAM的存储器的地址进行修改。对地址的改动基于要传送数据的大小,如下所示:
    在这里插入图片描述在这里插入图片描述
    使用上面的逻辑,对地址总线最后两个LSB取反,数据不变,对应HDL代码如下:

    assign	le_ram_addr[31:0] = (Size = 8-bits) ? 
    							{ram_addr[31:2], ~ram_addr[1], ~ram_addr[0]};
    							(Size = 16-bits) ? 
    							{ram_addr[31:1], ~ram_addr[0], ~ram_addr};
    
    assign	le_ram_data[31:0] = data[31:0];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用上面的方案可以使字节顺序转换对软件透明,并能确保数据完整性在字节顺序转换过程中不会被破坏。

    从小端设备到大端存储器,并保持数据不变的数据流如下所述:
    1)DMA发出对外设存储器的读字节操作。
    2)若系统产生的地址为0x00,在数据变化的实现中,小端模式设备RAM所看到的地址为0x03。
    3)设备存储器对该地址解码,访问位31:24即Type域。
    4)外设输出该值为{Type, 0x000000} (32位输出)。
    5)DMA对系统的大端存储器发出按字节方式的写操作。
    6)再次产生0x00地址(字节访问)。
    7)大端存储器将该访问解码为写入位31:24。
    8)由于来自于小端存储器的数据处于同样的字节区域,因此可以保持数据的完整性并将数据保存在大端RAM中。
    9)对其他需要从外设RAM传输到系统RAM中的数据继续进行该操作。
    10)16位和32位访问过程与上面所述相同,只是地址需要加以改变。

    • 地址不变

    与数据不变的字节顺序转换相比,某些应用程序或系统不需要数据保持特定的次序,但是需要在字节顺序转换后数据字节保持在同样的地址区域。这时就需要使用地址不变的字节顺序变换。

    参考同一个接收连续帧的例子,对于地址不变的系统,访问字节Type的地址偏移量永远是0x3。而在前一节中,访问该字节需要使用不同的地址偏移量。为了用硬件实现该过程,需要修改或交换从外设RAM中读到的数据值,RTL代码如下所示:

    assign	le_ram_addr[31:0] = ram_addr;
    assign	le_ram_data[31:0] = data[0:31];
    
    • 1
    • 2

    字节转换顺序如下图所示:

    在这里插入图片描述

    使用地址不变方式,从小端外设到大端存储器的数据流如下所述:
    1)DMA发出对外设存储器的读字节操作。
    2)若系统产生的地址为0x00,地址不变的实现使地址值始终相同。
    3)外设RAM对该地址解码,访问位[7:0]或H0区域。
    4)外设输出的数据为{0x000000, H0} (32位输出)。由于字节顺序匹配时地址不变,给系统RAM的数据变为{H0,0x000000} 。
    5)DMA发出对系统大端存储器的字节写操作。
    6)再次产生地址0x00(字节访问)。
    7)大端存储器将该访问解码为写入位[31:24] 。
    8)在字节顺序转换完成后,从小端存储器读出的数据已处在同样的地址区域,把地址存入大端RAM。
    9)对其他需要从外设RAM传递到系统RAM的字节继续进行以上操作。
    10)对16位或32位的访问,上述过程是相同的,只需将输出的数据进行交换即可。

    • 软件字节交换

    交换字节是实现字节顺序转换的一种方式。在由应用程序本身决定字节顺序的系统中,该模式是有用的。因此,无需用硬件实现这种字节顺序匹配过程。字节顺序中性代码的字节交换方法使用字节交换控制来决定是否必须进行字节交换过程。

    在软件中通常使用的各种字节交换方法有:
    1)交换汇编指令。
    2)用于交换字节的软件库宏。
    3)协议特定的交换函数。
    4)制定的交换函数。

    该方法的限制在于,在软件中实现交换功能会增加额外开支。位交换所引起的软件开支虽然存在,但是在需要处理的包的数量很多时开支引起的问题很容易修复,特别是在高频处理器中。

    6.字节顺序中性代码

    避免由字节顺序所引发问题的最好方法是在设计中使用字节顺序中性。可以通过两种途径完成这一任务:

    • 将字节顺序选项作为软件可配置的选项。
    • 在设计(IP)中使用字节使能,并将解码的任务留给系统或SOC。

    7.字节顺序中性编码指南

    字节顺序中性代码可以通过标识外部软件接口实现,遵循下面的指南来访问这种接口:

    • 数据存储和共享存储体,数据必须以独立于字节顺序体系结构的格式保存。
    • 字节交换宏,宏(或包装器)能用于所有多字节数据接口进行交换操作。
    • 数据传送,可以建立特定宏来从网络读数据或将数据写到网络中。根据输入数据的类型(如果它与本地主机字节顺序格式不匹配),可用宏来进行批量字节的交换。
    • 位域,避免定义跨越字节边界的位域。
    • 编译器指令,在使用会影响到数据存储(对齐、包装)的编译指令时要小心。指令在不同编译器之间并不是总能移植的。

    遵守字节顺序中性指南能使代码有更好的移植性,可以使同一源码运行在不同字节顺序结构的处理器上,从而减少了平台移植时的负担。

  • 相关阅读:
    golang singleflight资料整理
    Linux学习笔记-Ubuntu系统下配置用户ssh只能访问git仓库
    leetcode做题笔记2760. 最长奇偶子数组
    搭建一个自定义的工作流管理平台(二)
    专访 Web3Go 新产品 Reiki:培育 AI 原生数字资产与创意新土壤
    医学图像处理——DeepDrr工具CT生成DRR
    “毛细血管”的进化:华为分销业务如何让伙伴也有“高能级”
    设计模式之创建型模式
    【斗罗二】霍雨浩迷惑审查,戴华斌故意挑衅,惨败者屈服下跪
    【Maven学习】3.7 实验七:测试依赖的传递性
  • 原文地址:https://blog.csdn.net/Sisyphus415/article/details/128173233