当前位置:网站首页>复旦微FMQL(国产Zynq) 【IAR裸机开发之PS】——非字节对齐访问
复旦微FMQL(国产Zynq) 【IAR裸机开发之PS】——非字节对齐访问
2022-07-17 04:33:00 【奥利奥冰茶】
关注+星标公众号,及时获取更多技术分享~

作者 | 冰茶奥利奥
微信公众号 | 嵌入式电子创客街
在x86架构下,我们经常会有这种操作:
uint8_t TestBytes[10] = {0, 1, 2, 3, 4, 5, 6, 7};
uint32_t IntData;
IntData = *(uint32_t *&)TestBytes[2];
//输出结果
>>IntData = 0x05040302; //大端
>>IntData = 0x02030405; //小端对一个单字节数组进行取地址,然后强制转换为整数指针后取值,再赋值给IntData变量。
这样赋值后,如果CPU是常规的小端模式(Little End)的话,IntData的赋值结果就是0x5432;如果是大端模式的话,就是0x2345。相当于把数组TestBytes里的元素值依次赋给了IntData的四个字节。如下图所示:

使用地址强制取值操作
白嫖君在以前使用过的芯片中都这样操作过,包括Cortex-M3、M4,还有PowerPC架构的,还有Linux平台下也是这样使用的。但是最近在使用复旦微的Fmql芯片时,在程序里进行了类似的操作,结果程序直接就进入地址访问异常中断了。
白嫖君表示不理解,难道自己的认知有什么局限性吗?我大致猜测和地址对齐是有关系的。于是白嫖君做了个试验,把代码改成下面这样就能够正确执行:
uint8_t TestBytes[10] = {0, 1, 2, 3, 4, 5, 6, 7};
uint32_t IntData;
IntData = *(uint32_t *&)TestBytes[4];
uint16_t ShortData;
ShortData= *(uint16_t *&)TestBytes[2];
//输出结果
>>IntData = 0x07060504;
>>ShortData = 0x0302;从这次的结果可以看到,只要取得数据地址是按照字节对齐的,就能够正常执行,否则就会执行异常。
或许是因为堆栈定义在DDR的问题么?毕竟DDR的地址取用一次是64位的。于是白嫖君重新写了个程序,把堆栈定义在芯片内部的RAM中,现象一致,说明并不是DDR的问题,可是之前用Xilinx的芯片也没有类似的问题啊!
莫非是IAR的问题吗?白嫖君上网搜索后发现有人用Keil做实验,也出现过这种现象,但是在stm32上做却能正常执行。原来在《Cortex-M3权威指南》中有写道:
The Cortex-M3 processor also supports unaligned data accesses, a feature previously available only in high-end processors.
大概意思就是说,Cortex-M3 处理器还支持非对齐的数据访问,这是以前仅在高端处理器中可用的功能... 好吧知道你厉害行了吧?在这里我们注意到了一个词:unaligned access(非对齐访问),也就是这篇文章的核心了。下面这张图形象的展示了芯片非对齐访问时的实际操作步骤:即跨对齐边界,底层要拆成两个访问 ,然后把数据合并之返回,这个是指令底层微架构,软件层是看不到底层细节的。

非对齐访问指令层操作
Cortex-M3支持非字节对齐访问,那么我们用的Fmql的ARM核支持吗?莫非是芯片架构的问题?白嫖君在前面的文章中提到过,Xilinx用的是两片Cortex-A9,而复旦微用的是四片Cortex-A7,是不是这两种芯片有什么细微的差异呢?
查阅了一系列资料后,白嫖君发现,自从ARM-v7架构后,都支持了非对齐访问,我们常用的Cortex-M3和M4就属于ARM-v7架构,A7和A9两种芯片也都是该架构下的。

ARM-v7架构支持的子架构
那么既然芯片是支持非对齐访问的,还有什么原因会导致执行出错呢?别急,非对齐访问还是有条件的:
SCTRL.A寄存器必须配置为0;
只有部分访存指令支持非对齐访问;
所访问的地址空间存储器类型不能为strongly-order或device-memory;
编译器使能了非对齐访问。
怎么理解这4个条件呢?

ARM-v7支持非对齐访问的条件
从上图可以看到汇编指令LDRB,LDRH,LDR,分别对应 C语言的char,short,int。LDRB是按字节访存的,没有对齐要求,LDRH是2字节对齐(地址要求是 2的倍数),LDR则是4字节对齐(地址要求是4的倍数)。
那么白嫖君就把问题定位到第3条和第4条了,针对第4条,首先检查IAR的设置,网络上有一个答案说在IAR的编译选型里加上一条“–no_unaligned_access”语句,但是这只是让编译器避免编译出非对齐访问的情况,对于我们这种强制非对齐访问的根本起不到什么作用。
既然问题的根本不在编译器,那么白嫖君的问题出在哪了呢?其实是在MMU Table表里面。首先要使能MMU,就是分页内存管理单元,如果不使能,直接按strongly-ordered处理(类似寄存器的地址都是无法非对齐访问的)。

非对齐访问必须使能MMU
那么为啥在Cortex-M3、M4里不需要使能MMU呢?因为它本身就没有MMU啊。

那么使能MMU后,怎么才能更改存储空间的属性呢?在mmu_table.s里面看到这行语句。
/* (DDR Cacheable) */
SECT set SECT+0x100000
rept DDR_REG_CACHE
/* S=b0 TEX=b000 AP=b11, Domain=b0000, C=b0, B=b0 */
/*重点是这个值*/
DC32 SECT + 0xC02
SECT set SECT+0x100000
endr这个0xC02就是把这片存储空间定义成了device memory,就是前面提到的不能非对齐访问的情况;那么怎么修改呢?改成normal memory属性。
/* (DDR Cacheable) */
SECT set SECT+0x100000
rept DDR_REG_CACHE
/* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */
/*重点是这个值*/
DC32 SECT + 0x15DE6
SECT set SECT+0x100000
endr我们从ARM的手册里可以看到如何去定义memory的属性,如下图所示:

memory属性描述表
白嫖君把memory属性设置成了可读可写的normal memory,这样就能愉快地非对齐访问了~
但是根据这次的教训,我们得知,非字节对齐访问并不是所有的芯片都能支持的,比如Cortex-M0,所以我们编程的时候,还是要尽量避免非字节对齐访问的操作,以提高我们程序的可移植性。
如果您觉得这篇文章帮到了你,请点赞或者留下您的评论,您的鼓励是我前进的动力~
关注博主公众号 “嵌入式电子创客街” 获取更多及时技术分享~
关注+星标公众号,及时获取更多技术分享~

边栏推荐
- Common go file writing methods
- tf.AUTO_REUSE的作用
- Delete the file unable to find or create trash directory
- 高仿网易云音乐UI的微信小程序源码
- 状态码含义详解
- Autojs learning-2048 small game automation
- Cannot find module ‘process‘ or its corresponding type declarations.
- 如何配置Binlog
- Architecture and application of secure multiparty computing
- JS中Class类的静态属性和静态方法
猜你喜欢

Wechat e-book reading of small program graduation design (5) task book

Wechat e-book reading applet graduation project (8) graduation project thesis template

Wechat e-book reading applet graduation project (6) opening defense ppt

C语言动态内存开辟和柔性数组

By voting for the destruction of STI by Dao, seektiger is truly community driven

异或和加密方式的解密的复现

Touchid and faceid~2

Data types of basic knowledge of C language

OSPF comprehensive experiment

priority_ Introduction and use of queue
随机推荐
Wechat e-book reading of small program graduation design (5) task book
Gin framework principle
B+ tree stored procedures, triggers, substring and substr, and truncate and delete
The author of surging issued the pressure test results
MySQL InnoDB transaction related records
高仿网易云音乐UI的微信小程序源码
Cannot find module ‘process‘ or its corresponding type declarations.
ospf防环
HCR慧辰北坡而行,一只游入数字营销服务的巨兽
C语言动态内存开辟和柔性数组
64. Minimum path sum: given an M x n grid containing non negative integers, please find a path from the upper left corner to the lower right corner, so that the sum of the numbers on the path is the m
Xcode11 add a boot page (the launch images source option is missing after the upgrade)
Hello World driver
策略模式代替if-else
Data types of basic knowledge of C language
如何进行mysql下的严格模式修改,使得使用插入用户表方式添加新用户成功
Fetch request - simple record
分布式笔记(02)— 分布式缓存之 Redis(用途、特点、高可用方案 Redis Cluster、Twemproxy、Codis 简要说明)
[wechat applet] super easy to understand conditional rendering and list rendering
Impersonate the server for requests