存储器(Memory)作为计算机系统的重要组成部分,可分为RAM,ROM。可以是片内,也可在片外。一般来说,片内容量小,速度较快一些,片外的容量大,速度较慢一些。
片内/片外 是针对于MCU而言,而不同芯片厂家的MCU芯片,都可以采用同样的内核,比如说CM3。
CM3提供了预先定义好的存储器地址映射表,极大的方便了软件在各种基于CM3的MCU间的移植。
1 存储系统功能概览
CM3 的存储器系统与从传统 ARM 架构的相比,已经脱胎换骨了:
第一, 它的存储器映射是预定义的, 并且还规定好了哪个位置使用哪条总线。
第二, CM3 的存储器系统支持所谓的“位带”( bit‐band)操作。
第三, CM3 的存储器系统支持非对齐访问和互斥访问。 这两个特性是直到了 v7M 时才
出来的。
最后, CM3 的存储器系统支持小端配置和大端配置。
2 存储器映射
主要分为6大区域:
1 code区,存放指令,只读不可改,一般是flash
2 sram区,存放数据,片内静态ram,由芯片厂商决定使用多大的内存,可读可写
3 peripheral区,外设寄存器地址,由芯片厂商布局各式各样的外部设备
4 external ram区,片外扩展ram,当片内资源不够时,可进行扩展
5 external device区,片外扩展设备
6 private bus区,CM3内核的系统级组件,以及私有总线
3 位带操作
位带操作,在于通过访问字的方式来访问单个比特位,达到提高访问效率以及原子操作的目的,同时具有消耗了多余内存的缺点。
扩展成字的区域 称之为 位带别名区(bit-band alias)。
支持单个比特位扩展成字的区域 称之为 位带区(bit-band)。
支持位带操作的两个内存区的范围是:
0x2000_0000‐0x200F_FFFF( SRAM 区中的最低 1MB)
0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)
扩展的对应关系:(n为位序号(0<= n <= 7))
AliasAddr = 0x22000000+((A‐0x20000000)*8+n)*4 =0x22000000+ (A‐0x20000000)*32 + n*4;
’*8‘ 表示一个地址中存放了一个字节,一个字节中包含8位
’*4‘ 表示一个位扩展为32位的字,这样的一个字包含4个字节
为什么能够提高效率?
传统的写操作--读,改,写。包含这三步骤
位带的写操作--读,写。
传统的读操作--读,移位,提取。包含这三步骤
位带的读操作--总线单次读。
从以上汇编代码可以看出,通过操作位带别名区来操作位带区中的单个比特位,汇编指令较少,CPU执行效率较高。
在 C 语言中使用位带操作:
不幸的是,在 C 编译器中并没有直接支持位带操作。比如, C 编译器并不知道同一块内存能够使用不同的地址来访问,也不知道对位带别名区的访问只对 LSB 有效(最低位有效,因为最终作用到的是位带区的单个比特位,所以高位是无效的)。欲在 C 中使用位带操作,最简单的做法就是#define 一个位带别名区的地址。例如:
#define DEVICE_REG0 ((volatile unsigned long *) (0x40000000))
这里注意的是关键字 volatile
volatile 本意是指”易变的“,目的在于告诉编译器:”这个变量(内存区域)是容易改变的,不要进行编译优化(存放在寄存器中,或者cache中,来提高执行效率)“。因为一旦优化了,CPU每次对这块区域的访问不再是如实的读写内存,而是与寄存器(或cache)进行数据交互,最后才把结果写回内存,这样的话,若其他地方对该内存进行的修改,将不能被及时知晓,从而导致数据丢失或出错。
4 非对齐访问
在ARMv6之前,是不支持非对齐访问的,一旦非对齐访问,将引发异常。
在CM3(ARMv7-M)中,支持非对齐访问,但是,非对齐的数据传送只发生在常规的数据传送指令中,如 LDR/LDRH/LDRSH/STR。
其它指令则不支持,包括:
1 多个数据的加载/存储(LDM/STM)
2 堆栈操作 PUSH/POP。堆栈指针SP(R13)的最低两位默认为0,也就是表示了四字节对齐
3 互斥访问(LDREX/STREX)。如果非对齐会导致 fault
4 位带操作。因为只有 LSB 有效,非对齐的访问会导致不可预料的结果。
关于内存对齐的细节,可以参考:内存对齐 到底怎么回事?