隔壁Cortex-M0也不支持非对齐地址访问,代码中uint8_t*指针一旦强转uint16_t*或者uint32_t*,很容易引起HardFault。然而M3/M4就支持非对齐地址访问了,很多历史代码中会存在上面的强制地址转换,M3和M4上运行正常的代码移植到RISC-V以后非常容易踩到地址对齐的坑,代码规模比较大的时候填这些坑还是非常麻烦的。
RV32MAC假想对手是整个Cortex-M系列,M0是整个Cortex-M里面最低端的系列,RISC-V起码应该和M3/M4差不多,非对齐地址访问起码应该作为一个选项存在。
离线
是否支持非对齐访问,是实现层面的问题,,RISC-V ISA 本身并不限制是否支持非对齐访问。。
离线
《手把手教你设计CPU——RISC-V处理器》上的说明
离线
是否支持非对齐访问,是实现层面的问题,,RISC-V ISA 本身并不限制是否支持非对齐访问。。
人家隔壁ARM M0/M3/M4是不是支持是规定了的,这种模棱两可,依赖厂家来实现对齐、非对齐结果就是碎片化。RISC-V应该有一个扩展来约束是否支持非对齐访问操作。
离线
对齐不对齐,是软件设计方面的问题。
另外,非对齐数据,访问会需要更多的时间周期。
自己设计软件的时候,尽量把数据放在对齐地址上。
同样功能的代码,有些人的代码跑得就是比别人的快,这是有原因的。
离线
编译器应该可以处理
离线
GCC编译器的特定优化选项会自动将不对齐的操作转为对齐操作。
编译器能力是有限的,uint8_t*指针强制转换uint32_t*编译器就无法处理,大概率会跪。很多解析二进制数据的代码都会这么干。规模庞大的代码填这些坑就非常麻烦。
离线
非对齐地址可以用c语言强制类型转换,将任意结构体强转到char类型的数组访问
离线
这不是cpu内核的事情,cpu内核只是在偶数地址上按照字长的步进幅度增长地址指针,但是你要在奇数地址上保存,也是没有问题,只不过只能用char类型数组了. 其他的结构体,超过1字节长度的变量,编译器都会分配到偶数地址上. 当然,部分编译器你可以有伪指令限制,告诉编译器将你需要的某个变量定义到你指定的地址上(汇编是必须可以的,c语言不同的cpu以及不同的c编译器有不同的伪指令)
离线
uint8_t*指针一旦强转uint16_t*或者uint32_t*
uint8_t*强转到uint16_t*等,你必须要将转换后到的变量再与0xff, 否则得到的不是你想要的. 除非在接下来的3个地址空间上都是0.
最近编辑记录 aquasnake (2024-04-08 00:01:17)
离线
把uint8_t* 指向的实际对象,放在对齐变量,就没有任何问题。
比如:
int i;
uint8_t str[512];
uint8_t* t =(uint8_t*)&str[0];
然后,你再给int* p=(int*)t;
再计算, p++; p+=12; 之类, 都 没有问题。
另外,用malloc()分配的内存,肯定是对齐的。
离线
把uint8_t* 指向的实际对象,放在对齐变量,就没有任何问题。
比如:
int i;
uint8_t str[512];
uint8_t* t =(uint8_t*)&str[0];
然后,你再给int* p=(int*)t;
这个就是对齐访问啊。如果str[0]是头 str[1]以后是数据
用uint8_t* t =(uint8_t*)&str[1];
这时候用int* p=(int*)t; p可能会有不对齐的情况。
离线
碰到过一个杰理的,不对齐直接卡死,关键是程序中是网络编程,对齐不一定是4字节对齐
离线