CH57x的32位寄存器的问题

1623554085469005.png

1623554085116158.png

随便选了个32位寄存器,LCD的,使用数据变量指针指向,没啥问题,打印都正常。

1623554186116162.png

1623554199182620.png

定义个测试用的结构体(一开始用的联合体,以为联合体的问题,结果结构体一样的出错),很简单,赋值却出错。

RAM赋值.PNG还是同样的程序,把地址换成RAM 的地址,哎,又好了。证明结构体访问没啥问题。

结构体指针.PNG以为结构体不能这样写,结果使用结构体指向,也是正常的。

结构体指针指向变量.PNG然后结构体指向同样的数值的变量,不行,就奇了踏马的怪了。

数据指针指向变量.PNG

数据变量指针指向又行了。


也不能说不能用结构体写,我写了好多个外设了,8位16位寄存器用的好好的,USB通讯正常的很。

写TMR,来个32位寄存器,就出了这个问题。

头都要搞晕了。

不会汇编,不然去扒keil生成的汇编了,看是不是编译器优化了什么。

官方有无大佬解释一下?


尝试按照描述复现, 却始终没能复现楼主问题,

建议直接提供能复现的工程,包括原始能复现问题的固件.


发送到哪个邮箱?


发了有段时间了,有无音信?


大概看了下代码:

不同表现的代码是:

    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 )





哦哦,又学到了新知识


感谢指导


只有登录才能回复,可以选择微信账号登录