大概看了下代码:
不同表现的代码是:
uint32_t temp = 0x4000200C;
TEST_T *test = (TEST_T *)0x4000200C;
test->VAL = 100;
这种写法本身并没有问题,至于为什么产生问题,我们看下汇编差异:
//正常
;;;95 //---------------------------------------------------
;;;96 uint32_t temp = 0x4000200C;;
000016 4c0b LDR r4,|L1.68|
;;;97 TEST_T *test = (TEST_T *)0x4000200C;
000018 4625 MOV r5,r4
;;;98 test->VAL = 100;
00001a 2064 MOVS r0,#0x64
00001c 6028 STR r0,[r5,#0]
;;;99 //----------------------------------------------------
//不正常
;;;95 //---------------------------------------------------
;;;96 uint32_t temp = 0x4000200C;;
000016 4c0c LDR r4,|L1.72|
;;;97 TEST_T *test = (TEST_T *)0x4000200C;
000018 4625 MOV r5,r4
;;;98 test->VAL = 100;
00001a 4629 MOV r1,r5
00001c 2064 MOVS r0,#0x64
00001e f7fffffe BL __aeabi_uwrite4
;;;99 //----------------------------------------------------
从汇编结果上看, 只有最后一句不一样, 正常的是调用了STR指令;
而异常的是调用了一个函数__aeabi_uwrite4,
这里,已经能基本确确定问题了:
__aeabi_uwrite4 是处理非对齐的 uint32_t 时候用的,其实现相当于按uint8_t 或者uint16_t去拼数据, 而32bit的寄存器并不能这样操作(可以定义一个uint8_t 的数组去指向这些寄存器,按uint8_t 写去测试).
至于为什么你的工程 会调用 __aeabi_uwrite4, 经查发现,你在你做的头文件里面,有使用按照1字节对齐的约束:#pragma pack( 1 ),但是这个文件后面并没有恢复 到默认对齐到4字节, 而导致但凡include 你这个头文件后的的 结构体定义, 编译器都会按照#pragma pack( 1) 的方式处理, 最终编译时候 使用了__aeabi_uwrite4 操作test->VAL.
解决方法:
1,#pragma pack( 1 )约束相关的类型后, 使用#pragma pack( 4 ), 或者#pragma pack() 恢复默认对齐到4字节
2, 按照下面方式定义 TEST_T
#pragma pack( 4 )
typedef struct
{
uint32_t VAL;
}TEST_T;
#pragma pack( 1 )
大概看了下代码:
不同表现的代码是:
uint32_t temp = 0x4000200C;
TEST_T *test = (TEST_T *)0x4000200C;
test->VAL = 100;
这种写法本身并没有问题,至于为什么产生问题,我们看下汇编差异:
//正常
;;;95 //---------------------------------------------------
;;;96 uint32_t temp = 0x4000200C;;
000016 4c0b LDR r4,|L1.68|
;;;97 TEST_T *test = (TEST_T *)0x4000200C;
000018 4625 MOV r5,r4
;;;98 test->VAL = 100;
00001a 2064 MOVS r0,#0x64
00001c 6028 STR r0,[r5,#0]
;;;99 //----------------------------------------------------
//不正常
;;;95 //---------------------------------------------------
;;;96 uint32_t temp = 0x4000200C;;
000016 4c0c LDR r4,|L1.72|
;;;97 TEST_T *test = (TEST_T *)0x4000200C;
000018 4625 MOV r5,r4
;;;98 test->VAL = 100;
00001a 4629 MOV r1,r5
00001c 2064 MOVS r0,#0x64
00001e f7fffffe BL __aeabi_uwrite4
;;;99 //----------------------------------------------------
从汇编结果上看, 只有最后一句不一样, 正常的是调用了STR指令;
而异常的是调用了一个函数__aeabi_uwrite4,
这里,已经能基本确确定问题了:
__aeabi_uwrite4 是处理非对齐的 uint32_t 时候用的,其实现相当于按uint8_t 或者uint16_t去拼数据, 而32bit的寄存器并不能这样操作(可以定义一个uint8_t 的数组去指向这些寄存器,按uint8_t 写去测试).
至于为什么你的工程 会调用 __aeabi_uwrite4, 经查发现,你在你做的头文件里面,有使用按照1字节对齐的约束:#pragma pack( 1 ),但是这个文件后面并没有恢复 到默认对齐到4字节, 而导致但凡include 你这个头文件后的的 结构体定义, 编译器都会按照#pragma pack( 1) 的方式处理, 最终编译时候 使用了__aeabi_uwrite4 操作test->VAL.
解决方法:
1,#pragma pack( 1 )约束相关的类型后, 使用#pragma pack( 4 ), 或者#pragma pack() 恢复默认对齐到4字节
2, 按照下面方式定义 TEST_T
#pragma pack( 4 )
typedef struct
{
uint32_t VAL;
}TEST_T;
#pragma pack( 1 )
举报