ARM-v7 数据大小端转换实现

1.前言

        什么是大小端转换?为什么叫大小端转换?

        Jonathan Swift的《格列佛游记》中记载,有两国因为剥鸡蛋的方式不同,即一国要求将熟鸡蛋的较大的一端(大端,big endian)敲碎然后剥壳,另一个国家则强制要求敲碎鸡蛋的小端(little endian)。两国无法达成一致,进而交战多年。

        一位名为Danny Cohen的网络协议先驱者,将这两个数据用来描述数据在存储器中的排布方式,进而被广泛使用。例如对于一个四字节数据int data = 0x12345678,将低地址视为敲鸡蛋的地面,则有两种存储分布方式:

156fb2610cc54d039277bd328e672fee.jpeg

 图1 大小端字节序示意图

        如图1所示,data的高字节为0x12,所以左侧的为大端存储顺序,右侧为小端存储顺序。

        CPU的厂家众多,对于数据在存储器中的排布方式,也分为两个派系:

CPU Endian
Intel X86Little-Endian
Power-PC/IBMBig-Endian
ARM默认Little-Endian, 可配置Big-Endian

        大小端模式各有优劣,在小端模式下,指针的强制类型转换不需要调整字节内容,如short * (&data),取的是data低地址的两字节0x56和0x78,对应的也是data较低的16位;大端模式下,数据的符号位固定为第一个字节的最高bit,容易判断符号位,且和人类阅读方式相同,即先写数据的高位,再写数据的低位。

        以上讨论的是字节序大小端,事实上,比特(bit)序也存在大小端模式,规则类似,大端的高bit在低地址,小端相反。在定义C语言结构体时,如果存在位段的定义,则需要使各bit与CPU的大小端一致。例如:

typedef struct
{
    uint32 b2LatValSts:2;               //bit 31~30 
    uint32 b2YawRateValSts:2;           //bit 29~28
    uint32 b3EpbSts:3;                  //bit 27~25
    uint32 b1BrakePressSts:1;           //bit 24
    uint32 b2BrakePedlSts:2;            //bit 23~22
    uint32 b2TurnIndicatorSwtichSts:2;  //bit 21~20
    uint32 b3EpsSts:3;                  //bit 19~17
    uint32 b1SteerWhlAngDir:1;          //bit 16
    uint32 b1SteerWhlAngSpdDir:1;       //bit 15
    uint32 b15Reserved:15;              //bit 0~14
}BIG_ENDIAN_SAMPLE_ST_TYPE;

typedef struct
{
    uint32 b15Reserved:15;              //bit 0~14
    uint32 b1SteerWhlAngSpdDir:1;       //bit 15
    uint32 b1SteerWhlAngDir:1;          //bit 16
    uint32 b3EpsSts:3;                  //bit 19~17
    uint32 b2TurnIndicatorSwtichSts:2;  //bit 21~20
    uint32 b2BrakePedlSts:2;            //bit 23~22
    uint32 b1BrakePressSts:1;           //bit 24
    uint32 b3EpbSts:3;                  //bit 27~25
    uint32 b2YawRateValSts:2;           //bit 29~28
    uint32 b2LatValSts:2;               //bit 31~30 
}LITTLE_ENDIAN_SAMPLE_ST_TYPE;

        由于Power-PC在网络领域的统治地位,以及其他可能存在的原因,总之网络字节序完成了江湖大一统,统一使用大端字节序。进而,在应用软件开发时,经常需要对网络数据接口进行大小端转换,这个转换主要时针对字节序。那比特序呢?这个通常不需要应用层来做转换,可以姑且理解为某个底层协议栈帮忙做转换了,只需要在应用软件本地按自身CPU的大小端来定义位段即可。

2.大小端转换

2.1 通用的C语言字节序转换方法

#define M_2BYTES_ENDIAN_CONVERT(src)  ((src) = ((typeof(src))0xFF00 & ((src) << 8)) | ((typeof(src))0x00FF & ((src) >> 8)))
#define M_4BYTES_ENDIAN_CONVERT(src)  ((src) = ((typeof(src))0xFF000000 & ((src) << 24)) | ((typeof(src))0x00FF0000 & ((src) << 8))  |((typeof(src))0x0000FF00 & ((src) >> 8)) | ((typeof(src))0x000000FF & ((src) >> 24)))

        这里不多说,具体见上述代码中的两个宏定义。

2.2 CMSIS

        Common Microcontroller Software Interface Standard(CMSIS),是ARM封装的Cortex-M架构微控制器的标准软件接口规范。 显然,这里要说的是ARM针对大小端优化所给出的汇编级指令,但还是通过CMSIS标准接口来使用。

2.2.1 大小端转换的相关ARM指令(Cortex-M

指令解释
REV {condition} Rd, Rn

转换word的字节序,一个word为4字节

REV16 {condition} Rd, Rn转换half word的字节序,half word即为2字节
REVSH {condition} Rd, Rn转换低half word的字节序,并符号拓展至32位(4字节)
RBIT{condition} Rd, Rn对一个32位的word(字)进行比特序大小端转换

        其中,Rd是目标寄存器(destination register), Rn是操作数寄存器(the register holding the operand),conditon是操作条件码。例如:

REV R3, R7   ; Reverse byte order of value in R7 and write it to R3.
REV16 R0, R0 ; Reverse byte order of each 16-bit halfword in R0.
REVSH R0, R5 ; Reverse Signed Halfword of R5 and sing extend to 32 bits and then write to R0
REVHS R3, R7 ; Reverse with Higher or Same condition.
RBIT R7, R8  ; Reverse bit order of value in R8 and write the result to R7

2.2.2 CMSIS接口

        例如在cmsis_gcc.h中定义有以下内联函数:

#define __CMSIS_GCC_USE_REG(r) "r" (r)

/**
  \brief   Reverse byte order (32 bit)
  \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
  \param [in]    value  Value to reverse
  \return               Reversed value
 */
__STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
  return __builtin_bswap32(value);
#else
  uint32_t result;

  __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
  return result;
#endif
}

/**
  \brief   Reverse byte order (16 bit)
  \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
  \param [in]    value  Value to reverse
  \return               Reversed value
 */
__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
{
  uint32_t result;

  __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
  return result;
}

/**
  \brief   Reverse byte order (16 bit)
  \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
  \param [in]    value  Value to reverse
  \return               Reversed value
 */
__STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
  return (int16_t)__builtin_bswap16(value);
#else
  int16_t result;

  __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
  return result;
#endif
}

/**
  \brief   Reverse bit order of value
  \details Reverses the bit order of the given value.
  \param [in]    value  Value to reverse
  \return               Reversed value
 */
__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
{
  uint32_t result;

#if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
     (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
     (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
   __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
#else
  uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */

  result = value;                      /* r will be reversed bits of v; first get LSB of v */
  for (value >>= 1U; value != 0U; value >>= 1U)
  {
    result <<= 1U;
    result |= value & 1U;
    s--;
  }
  result <<= s;                        /* shift when v's highest bits are zero */
#endif
  return result;
}

        值得注意的是:

        ① 该接口中,包含了使用gcc builtin的转换函数和使用ARM-v7汇编指令两种方式,显然后者效率更高;

        ② int16_t __REVSH(int16_t value)函数中,result的类型是int16_t,即有符号的16位数据类型,运算过程中将拓展后的32位有符号数据截断并返还低16位数据;

3. 总结

        如果当前的CPU是ARM的Cortex-M架构微控制器,建议使用标准的CMSIS接口来进行大小端转换,不仅效率高,软件移植性也会更好。

  • 33
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
### 回答1: ARM-V7处理器具有以下优势: 1. 高效能:ARM-V7处理器采用了先进的流水线技术,能够实现高速的运算和数据传输,同时其能够支持多核心处理,增强了处理能力。 2. 低功耗:ARM-V7处理器采用了低功耗设计,能够在不影响性能的情况下减少功耗,延长设备的使用时间。 3. 稳定性强:ARM-V7处理器采用了高度集成的架构,能够有效减少系统复杂度和故障率,提高设备的稳定性。 4. 兼容性好:ARM-V7处理器具有良好的兼容性,能够支持多种操作系统和应用程序,方便开发人员进行开发和调试。 5. 成本低:ARM-V7处理器成本较低,能够降低设备的制造成本,提高设备的市场竞争力。 ### 回答2: ARM-V7处理器是一种具有许多优势的处理器架构。首先,ARM-V7处理器具有高性能和低功耗的特点。它采用了先进的指令集架构和多核处理技术,可以处理复杂的任务和多线程应用程序,同时保持低功耗,延长设备的电池寿命。 其次,ARM-V7处理器具有广泛的应用领域。从消费电子产品到汽车、智能手机和嵌入式设备,ARM-V7处理器可以满足各种不同设备的需求。它的灵活性和可扩展性使其成为许多不同领域的首选处理器架构。 此外,ARM-V7处理器还具有较低的成本和较小的尺寸。由于其设计简单,制造成本低,可以在经济效益和性能之间取得良好的平衡。同时,ARM-V7处理器的尺寸较小,可以轻松集成到各种设备中,增加可设计的灵活性。 最后,ARM-V7处理器有着强大的生态系统和广泛的支持。许多厂商和开发者致力于开发和优化基于ARM-V7架构的软件和解决方案。这使得ARM-V7处理器拥有丰富的软件生态系统和开发工具,为开发者提供了更多的支持和便利。 综上所述,ARM-V7处理器具有高性能低功耗、广泛应用、低成本小尺寸以及强大的生态系统和支持等优势。这些优势使得ARM-V7处理器在各个领域都有广泛应用和深受青睐。 ### 回答3: ARM-V7处理器是一款低功耗、高性能的处理器,具备以下几个优势。 首先,ARM-V7处理器采用了精简指令集(RISC)架构,指令简单、执行速度快,可以更高效地处理指令和数据。这使得ARM-V7处理器在相同主频下,与其他处理器相比,具有更高的性能。 其次,ARM-V7处理器采用了先进的微架构设计,包括乱序执行、预取、超标量执行等技术。这些技术使得ARM-V7处理器在运行多线程应用时,能够更好地提高线程的并发度,加快指令的执行速度。 再次,ARM-V7处理器具有低功耗的特点。它采用了先进的电源管理技术,可以根据实际工作负载调整电压和频率,以实现功耗的优化。这使得ARM-V7处理器在移动设备等对功耗要求较高的场景中具有明显的优势,延长了设备的电池使用时间。 此外,ARM-V7处理器还支持一系列的硬件虚拟化技术,可以在同一处理器上同时运行多个操作系统或虚拟机。这种灵活性使得ARM-V7处理器在数据中心等对虚拟化支持较高的场景中具有优势。 综上所述,ARM-V7处理器具有高性能、低功耗、支持虚拟化等优势,适用于广泛的应用领域,包括移动设备、嵌入式系统、物联网等。它的使用可以提高设备的性能和续航能力,并为用户提供更好的使用体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值