微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 从STM32的位带操作重谈嵌入式中寻址与对齐的理解

从STM32的位带操作重谈嵌入式中寻址与对齐的理解

时间:11-19 来源:互联网 点击:

节(Byte),表示是4G个字节数,因此32位处理器寻址范围为4G个字节。

若觉得4GB内存对于一些运算觉得不够用,采用64位处理器就可以这一问题,我们看看64位的寻址范围↓

@-> 2^64=2^34 * 2^30=16G*G

看到了吧,寻址范围能有16G*G个字节,远远大于32位处理器,连跳好几个数量级,足够满足很多应用了。一般G*G就称为E了,即64位处理器寻址范围为16EB。不过这么大的数我是已经没什么概念了。

最早的红白机,任天堂的FC,是一台8位机(MOS 6502),小时候玩的红白机觉得画面简单音乐粗糙,与其CPU性能不无关系。FC的接班人超任SFC采用了摩托罗拉的65836,3.58MHz的16位CPU,游戏画面和音质明显上了一个档次。掌机GameBoy(GB)和GameBoyColor(GBC)同为8位机。之后的GBA和NDS均采用了ARM系列芯片则直接是32位机了。这个网址可以很方便地查看GBA和NDS的硬件参数。32位主机时代PlayStation是王者可以说毫无疑问,而PS2你猜猜有多少位?64?不,人家直接跳到128位了。天文数字不是么,虽然PS2的CPU(Emotion Engion 简称EE)主频只有295Mhz。所以说现在很多PC端的PS2模拟器并不能很好的模拟就是这个道理。而到了PS3时代又回到了64位。不过要理解,单纯追求CPU的带宽并不一定能带来画面和性能的提升,其中架构的合理,缓存、外设时钟等等都会影响性能。

之后,为什么所有这些数字,4GB,16EB后面都要加个B(字节),为什么存储的单位是字节?这个问题我们先放一放,先来看看字(Word)的概念。

如果说比特(bit),字节(Byte)的概念比较好理解,那么字(Word)的概念就容易把人搞晕了,因为,字的长度并不统一,在不同CPU,不同时代,字的长度并不一致。从前的8位机上,比如前面提到的红白机的MOS 6502,字长为8bit,即一个字节。在一些16位CPU上,比如著名的8086,字长是16位的,2个字节。而现在的32位CPU比如ARM和我们手中的PC,字长是32位,即4个字节。

可以参考这张wiki表对照历史上CPU们对字长的规定。

如果说,字节(Byte)对应于存储的单位大小,那么字(Word)则对应了CPU一次处理数据/指令的大小,因此才为了方便起了个字(Word)这个名字。对于ARM来说,字长是32位的,也就是4个字节。回想起ARM里所有的寄存器,是不是每个寄存器都是32位的?所以,以这个32位为单位进行操作,因此这个32位即为一个字(Word)。那么为什么之前说字节(Byte)是存储的基本单位呢?

对于ARM里面,数据的地址值跟数据自己本身都是32位的,这样做的好处是操作起来方便,统一。当然,对于ARMv4架构里的指令来说,有着32位的ARM指令集和16位的Thumb指令集,甚至对于Cortex M3来说都是32位或16位的Thumb指令集。这里先不讨论这种指令集之前的区别,仅仅以允许的最大指令为32位来讨论。另外,对于Cortex这一重回哈弗架构的CPU来说,指令和数据是分开的,完全可以不用同样的带宽访问(当然实际上STM32二者带宽还是一样的,方便操作,只是分开了而已)。有兴趣的可以参考这篇文章对照指令集与架构的区别。

现代主流CPU的存储单元为字节(Byte),即物理地址的编码是以字节为单位编码的,一个地址对应于一个字节(Byte)或8个bit的空间,这一地址加上1,则对应于下一个字节或下一组8bit。这种物理地址的编码方式是由CPU的架构所保证的,并且为现在主流CPU所采用,因此说32位CPU的寻址范围是4GB就是指可找到物理地址上总共4G范围的区域,每一个区域上都有1个字节(Byte)的空间用于存放数据或指令。

那么很明显,对于ARM的寄存器来说,一块这样的1个字节区域肯定是不够的,每个32位的寄存器需要4个这样的区域来存放才可以。我们经常可以看到在定义寄存器时使用了下面的语句↓

/* General Purpose Input/Output (GPIO) */#define IOPIN0         (*((volatile unsigned long *) 0xE0028000))#define IOSET0         (*((volatile unsigned long *) 0xE0028004))#define IODIR0         (*((volatile unsigned long *) 0xE0028008))#define IOCLR0         (*((volatile unsigned long *) 0xE002800C))#define IOPIN1         (*((volatile unsigned long *) 0xE0028010))#define IOSET1         (*((volatile unsigned long *) 0xE0028014))#define IODIR1         (*((volatile unsigned long *) 0xE0028018))#define IOCLR1         (*((volatile unsigned long *) 0xE002801C))

以上寄存器在内存里是相互连续的,我们可以很清楚的看到,他们之间的地址值的增量为4。这就很清楚了,相邻寄存器地址值差4

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top