目录
- 1.概述
- 2.存储器映射
- 3.程序存储器、Boot Loader和存储器重映射
- 4.数据存储器
- 5.支持小端和大端
- 数据类型
- 数据对齐
- 访问非法地址
- 多寄存器加载和存储指令的使用
- 6.存储器属性
1.概述
Cortex-M0处理器具有32位系统总线接口,以及32位地址线(4GB的地址空间)。系统总线基于AHB_Lite总线协议,外设总线一般采用APB协议。APB协议通过一个总线桥连接到AHB_Lite上,并且运行的时钟频率和AHB总线不同。APB的数据链路也是32位的,但由于外设的地址区域往往较小,因此地址线一般要少于32位。
由于主总线系统和外设总线是相互分离的,而且有些情况下时钟频率控制也是不同的,应用程序在访问外设前可能需要初始化微控制器的时钟控制硬件。有些情况下,一个微控制器可能有多个外设总线段,并且每个段运行在不同的时钟频率下。除了可以让系统的某些部分运行在较低频率下以外,独立的总线段还可以停止某些外设系统的时钟,这样也就可以降低功耗了。
2.存储器映射
Cortex-M0处理器的4GB存储器空间从架构上被分为多个区域,每个区域对应一种推荐的用途,而且各区域的操作方法也可能会有所不同。
尽管存储器映射已经被架构预先定义,存储器映射的实际用法却可以非常灵活,使用中的限制也不多。
每个区域的用途如下:
- 代码区域(0x00000000~0x1FFFFFFF)
代码区域的大小为512MB,主要用于存储代码,这其中也包括作为程序映像一部分的向量表,另外也可用作数据存储器(连接到RAM)。 - SRAM区域(0x20000000~0x3FFFFFFF)
SRAM区域位于存储器映射的第二个512MB,其主要用于数据存储,这其中也包括栈,还可以用于程序代码存储。 - 外设区域(0x40000000~0x5FFFFFFF)
外设区域的大小也为512MB,它主要用于外设以及数据存储。不过,外设区域中不允许执行程序。连接到该存储器区域的外设可以是AHB_Lite外设,也可以是APB外设(通过总线桥)。 - RAM区域(0x60000000~0x9FFFFFFF)
RAM区域包括两个512MB的块,这样就得到了一个总共1GB的区域。这两个512MB存储器块主要用于数据存储,而且多数情况下RAM区域可使用1GB的连续存储器空间。RAM区域中还可以执行程序代码,这两个区域的唯一差异在于它们的存储器属性不同。如果设计中存在一个系统级的缓存(level-2缓存),这个差异就会带来缓存行为的差异。 - 设备区域(0xA0000000~0xDFFFFFFF)
外部设备区域包括两个512MB的存储器块,这样就能总共得到1GB空间。两个512MB块主要用于外设和I/O,设备区域不允许程序执行,但可用作通用数据存储。同RAM区域类似,设备区域的两部分也有不同的存储器属性。 - 内部私有外设总线(PPB)(0xE0000000~0xE00FFFFF)
内部PPB存储器空间用于处理器内部的外设,包括中断控制器、NVIC和调试部件等。内部PPB存储器空间的大小为1MB,且这个区域内不允许执行程序。
在PPB存储区域中,有一段特殊的存储器区域被定义为系统控制空间(SCS),其地址范围为0xE000E000~0xE000EFFF。该区域内包括中断控制寄存器、系统控制寄存器和调试控制寄存器等,NVIC寄存器也是SCS存储器空间的一部分。 - 保留存储器空间(0xE0100000~0xFFFFFFFF)
存储器映射的最后511MB为保留存储器空间,这段空间在某些微控制器中预留为供应商特定的用途。
尽管Cortex-M0处理器的存储器映射是固定的,存储器的用法却可以非常灵活。例如,处理器可以在SRAM区域包含多个SRAM存储器块,CODE区域也是一样,而且外部RAM区域也可以执行程序。
在一个实际系统的存储器映射中,对于一个典型的Cortex-M0微控制器,通常可以在其中找到以下部分:
- Flash存储器(用于程序代码)
- 内部SRAM(用于数据)
- 内部外设
- 外部存储器接口(用于外部存储器和外部外设,可选)
- 其他外部外设的接口(可选)
将这些部件放到一起,就可以得到如下图所示的微控制器实例:
3.程序存储器、Boot Loader和存储器重映射
-
Cortex-M0的程序存储器一般使用片上Flash存储器,不过,程序也可以存储在外部或者使用其他类型的存储器设备(如EEPROM)。
当Cortex-M0处理器从复位中启动时,它会首先访问0地址的向量表,从而取得MSP的初始值和复位向量,然后它就可以从复位向量开始执行程序。要保证系统正常工作,系统中需要有合法的向量表和合法的程序存储器,这样处理器才不会执行恶意软件代码。 -
要实现这个目的,Flash存储器一般是从地址0开始的。不过,在用户编程以前,有些微控制器的Flash存储器中可能没有任何程序。为了保证处理器可以正确地启动,有些基于Cortex-M0的微控制器含有一个Boot loader,这是个位于微控制器芯片上的一小段程序,它会在处理器上电后执行并跳转,而且如果Flash存储器已编程的话,它会跳转到Flash中的用户程序执行。Boot loader由芯片供应商预先编程,有时它位于片上Flash存储器并且与用户程序是分离的(这样用户更新程序也不会影响到Boot loader),而其他情况下Boot loader则会位于和可编程程序存储器分离的非易失性存储器中(防止用户意外擦除Boot loader)。
-
当Boot loader存在时,微控制器通常会在系统总线上使用一种存储器映射切换特性,也就是重映射(remap)。存储器映射的切换由硬件寄存器控制,Boot loader执行时会重置这些寄存器。系统可以使用多种重映射方案,一种常见的处理是,Boot loader将会在上电阶段通过地址别名重映射到存储器的开头,如下图:
-
ARM微控制器使用的另外一种重映射特性为,SRAM块可以重映射到地址0上。微控制器使用的非易失性存储器如Flash等要比SRAM慢,如果微控制器运行在较高的时钟频率下,Flash存储器中的程序在执行时就会需要插入等待状态。而将SRAM重映射到地址0后,程序就可以被复制到SRAM并以最快速度执行,这样会避免取向量表时出现等待,否则会增加中断等待的时间。
4.数据存储器
Cortex-M0处理器的数据存储器用于软件变量、栈存储,而且有些情况下还用于堆存储。应用程序使用需要动态内存分配的C函数时,堆存储就可以用上。
如果嵌入式应用中没有操作系统(OS),那么它只会使用一个栈(只需主栈)。在这种情况下,数据存储器的分配如下所示:
由于栈操作基于满减小的栈分配,而堆存储在分配时是增加的。为了使存储分配最具效率,通常将栈放在存储器块的尾部,而堆存储则紧跟在普通存储的后面。
而对于使用了嵌入式OS的嵌入式应用程序来说,每个任务可能都会有自己的栈存储区域。每个任务都可以有自己分配的存储器块,每个存储器块都可以包含有栈、堆和数据。
5.支持小端和大端
- Cortex-M0处理器可以支持小端的存储器格式,也可以支持大端的。大小端在系统设计时由微控制器供应商选择,而软件不能修改。使用小端配置时,字数据的最低字节存储在字的位0到位7;而若采用大端配置,字数据的最低字节则会存储在位24到位31,如下所示。
这两种配置都支持不同大小的数据处理,Cortex-M0处理器可以产生字节、半字以及字传输。在访问存储器时,存储器接口会根据传输大小和地址的最低两位选择数据链路,如下所示:
应该注意大端配置有两种例外:取值总是小端的,且对私有外设总线(PPB)的访问总是小端的。
数据类型
Cortex-M0处理器支持各种不同的数据大小,提供了用于不同大小传输的各种存储器访问指令,而且还具有一个32位AHB_Lite接口,该接口支持32位、16位和8位传输。例如,C语言开发中常用到的数据类型如下所示:
如果使用了其他宽度更大的数据类型,C编译器会自动将这些数据传输转换为存储器访问指令。应该注意的是,对于外设寄存器访问,使用的数据类型应该同硬件寄存器大小相匹配。要不外设可能会忽略此次传输,或者运行结果同预想的不一致。
多数情况下,连接到APB的外设应该使用字传输来访问。这是因为APB协议没有定义传输宽度信号,所有的传输也就都被认为是字大小的。因此,通过APB访问的外设寄存器通常被声明为“volatile unsigned integer”。
数据对齐
Cortex-M0处理器支持的Thumb指令只能产生对齐访问。这就意味着传输地址只能是传输大小的整数倍。例如,字传输只能访问0x0、0x4、0x8和0xC之类的地址,与之类似,半字访问只能访问0x0、0x2、0x4等地址,所有的字节访问则都是对齐的。
如果程序试图进行一次非对齐访问,错误异常就会产生并且引发硬件错误处理的执行。
访问非法地址
在连接到Cortex-M0处理器的AHB系统中,地址解析逻辑会探测正在访问的地址,如果访问的是一个非法位置,总线系统就会回应一个错误信号,取值或数据访问都可以引起总线错误。
跳转影子指令的取值则是这种操作的一个例外,由于Cortex-M0处理器的流水线本性,指令会被提前取出。因此,如果程序执行到合法存储器区域的尾部,并且执行了一个跳转指令,这种情况下,处理器可能会预取一个合法指令存储器区域之外的地址,这就会导致AHB系统的总线错误。不过,如果由于跳转,错误指令没有得到执行,总线错误就会被忽略掉。
多寄存器加载和存储指令的使用
Cortex-M0处理器支持多寄存器加载和存储指令,如果使用正确的话,系统性能可以得到很大的提升。例如,它可以用于加快数据传输过程或者作为一种自动调整指针的方法。
6.存储器属性
Cortex-M0处理器可以使用多种存储器系统和设备,要使不同设备的软件移植更加容易,可以对存储器映射中的每个区域设置相应的存储器属性。存储器属性是存储器访问的特征,它们能够影响对存储器的数据和指令访问,对外设的访问也是一样。
在ARMv6-M架构中,不同的存储器区域可以定义多种存储器访问属性:
- 可执行(executable):这是个公用属性,它定义了程序是否允许在存储器区域中执行。根据ARM文档,如果一个存储器区域是不可执行的,它就会被标记为eXecuteNever(XN,永不执行)。
- 可缓冲(bufferable):在一个可缓冲存储器区域上执行数据写操作,写传输可能会被缓存起来,这就意味着处理器不必等待当前的写传输完成,就可以继续执行下一条指令。
- 可缓存(cacheable):如果系统中含有缓存设备,它可以在本地备份当前传输的数据,并可以下次在访问相同的存储器位置时重新使用,这样可以加速系统执行。缓存设备可以是一个缓存存储器单元,也可以是存储器控制器中的一个小的缓存。
- 可共享(shareable):可共享属性定义了多个处理器是否可以访问公用存储器区域,如果一块存储器区域是可共享的,存储器系统需要确保多个处理器访问这一区域时的一致性。
基于这些存储器属性,处理器架构上定义了多种类型的存储器,以及每个存储器区域可以使用哪种类型的设备:
- 普通存储器:可以是共享也可以是不共享的,可以是缓存的也可以是不缓存的。对于可缓存的存储器,缓存行为可以分为写通(WT)以及写回写分配(WBWT)。
- 设备存储器:设备存储器为不可缓存的,可以是共享的,也可以是不共享的。
- 强序存储器:这种存储器是不可缓存以及不可缓冲的,对强序区域的读写操作会立即起作用。另外,在这种存储器接口的传输顺序必须和相应的存储器访问指令的顺序一致。强序存储器区域总是可共享的。
Cortex-M0处理器中每个存储器区域的属性由这些存储器类型定义来决定,在存储器访问中,属性通过AHB系统从处理器中输出。
PPB存储器区域被定义为强序属性(SO),这就意味着存储器是不可缓存和不可缓冲的。对于Cortex-M0,在强序区域访问结束之前,后面的操作不会执行。这种处理适用于修改系统控制空间(SCS)的寄存器,此时一般希望在下一条指令执行前,对寄存器的修改操作就会立即执行。