Cortex-M3存储器系统
文章目录
存储系统功能概览
Cortex-M3 处理器的存储系统与传统的 ARM 架构相比,具有许多独特的功能和改进。以下是 Cortex-M3 存储系统的主要特点:
预定义的存储器映射
Cortex-M3 的存储器映射是预定义的,并且规定了每个位置使用哪条总线。这种预定义的映射简化了系统设计,确保了不同存储区域的高效访问。
位带操作
Cortex-M3 支持位带(bit-band)操作,允许对单一比特进行原子操作。位带操作仅适用于一些特殊的存储器区域,如 SRAM 和外设区域。通过位带操作,可以简化对单个比特的读写操作,提高系统性能。
非对齐访问
Cortex-M3 支持非对齐访问,允许对非字对齐的地址进行访问。这提高了存储器访问的灵活性,减少了数据对齐的要求。
互斥访问
Cortex-M3 支持互斥访问,允许对共享资源进行原子操作,避免数据竞争。互斥访问通过特定的指令实现,确保在多任务环境中数据的一致性。
小端和大端配置
Cortex-M3 的存储器系统支持 both 小端配置和大端配置。小端配置是默认设置,适用于大多数应用场景。大端配置则适用于特定的网络和通信协议
存储器映射
Cortex-M3 处理器的存储器映射是单一且固定的,这极大地方便了软件在不同 CM3 单片机之间的移植。尽管存储器映射是固定的,但芯片制造商仍然可以灵活地分配存储器空间,以制造出各具特色的单片机产品。
存储器映射概览
Cortex-M3 的地址空间为 4GB,分为多个区域,包括代码区、内部 SRAM 区、外部 RAM 区以及私有外设区。以下是各区域的主要功能:
代码区
代码区用于存储程序代码和常量数据。理想情况下,程序代码应放置在代码区,以便取指和数据访问各自使用不同的总线,提高并行处理能力。
内部 SRAM 区
内部 SRAM 区用于存储程序运行时的数据。SRAM 访问速度快,适合存储频繁访问的数据。
外部 RAM 区
外部 RAM 区用于存储需要更大容量的数据。外部 RAM 通常通过外部总线接口访问。
私有外设区
私有外设区用于调试组件等私有外设,包括:
-
闪存地址重载及断点单元(FPB):用于地址重载和断点调试。
-
数据观察点单元(DWT):用于数据观察点调试。
-
指令跟踪宏单元(ITM):用于指令跟踪。
-
嵌入式跟踪宏单元(ETM):用于嵌入式跟踪。
-
跟踪端口接口单元(TPIU):用于跟踪端口接口。
-
ROM 表:用于存储调试组件的配置信息。
存储器映射详解详解
ortex-M3 处理器的存储器映射是单一且固定的,分为多个区域,包括内部 SRAM 区、片上外设区、外部 RAM 区、外部设备区以及私有外设区。以下是各区域的主要功能和特点:
**
内部 SRAM 区
- 大小:512MB
- 用途:用于连接片上 SRAM,通过系统总线访问。
- 位带区:1MB 的位带区,对应 32MB 的位带别名区。位带别名区中的每个字对应位带区的一个比特,支持原子操作。
片上外设区
- 大小:512MB
- 用途:用于片上外设的寄存器。
- 位带别名区:32MB 的位带别名区,便于快捷访问外设寄存器。
- 限制:不允许执行指令。
外部 RAM 区
- 大小:1GB
- 用途:用于连接外部 RAM。
- 特点:允许执行指令。
外部设备区
- 大小:1GB
- 用途:用于连接外部设备。
- 限制:不允许执行指令。
私有外设区
- 大小:0.5GB
- 用途:用于系统级组件和内部私有外设总线。
- 私有外设总线:
- AHB 私有外设总线:用于 CM3 内部的 AHB 外设(如 NVIC、FPB、DWT 和 ITM)。
- APB 私有外设总线:用于 CM3 内部的 APB 设备和外部设备。
系统控制空间(SCS)
- 位置:位于私有外设区。
- 组件:包括 NVIC、SysTick、MPU 以及代码调试控制寄存器。
未用的提供商指定区
- 用途:通过系统总线访问,不允许执行指令。
存储器访问属性
Cortex-M3 处理器的存储器映射不仅定义了存储区域,还规定了每个区域的访问属性。这些属性包括可否缓冲(Bufferable)、可否缓存(Cacheable)、可否执行(Executable)和可否共享(Sharable)。如果配备了 MPU(内存保护单元),可以通过它配置不同的存储区,并覆盖默认的访问属性。
存储器访问属性详解
- 可否缓冲(Bufferable):
- 决定是否允许对存储器访问进行缓冲。缓冲可以提高访问速度,但可能导致数据不一致。
- 可否缓存(Cacheable):
- 决定是否允许对存储器访问进行缓存。缓存可以提高访问速度,但可能导致数据不一致。
- 可否执行(Executable):
- 决定是否允许在该存储区域执行指令。某些区域(如外设区)不允许执行指令。
- 可否共享(Sharable):
- 决定是否允许在多核系统中共享该存储区域。共享区域需要严格按顺序操作,以确保数据一致性。
存储器区域划分
Cortex-M3 的地址空间分为 8 个 512MB 等份,每个区域具有不同的访问属性:
- 代码区(0x0000_0000 - 0x1FFF_FFFF):
- 可执行指令。
- 缓存属性为 WT(写通,Write Through),不可缓存。
- 数据操作通过数据总线接口(读数据使用 D-Code,写数据使用 System)。
- 写操作是缓冲的。
- SRAM 区(0x2000_0000 - 0x3FFF_FFFF):
- 用于片内 SRAM。
- 写操作是缓冲的。
- 可以选择 WB-WA(写回,Write Back,写分配,Write Allocated)缓存属性。
- 可执行指令,允许将代码拷贝到内存中执行。
- 片上外设区(0x4000_0000 - 0x5FFF_FFFF):
- 用于片上外设。
- 不可缓存,不可执行指令(XN,eXecute Never)。
- 外部 RAM 区的前半段(0x6000_0000 - 0x7FFF_FFFF):
- 用于片外 RAM。
- 可缓存(缓存属性为 WB-WA),可执行指令。
- 外部 RAM 区的后半段(0x8000_0000 - 0x9FFF_FFFF):
- 除了不可缓存(WT)外,同前半段。
- 外部外设区的前半段(0xA000_0000 - 0xBFFF_FFFF):
- 用于片外外设的寄存器和多核系统中的共享内存。
- 不可缓存,不可执行指令。
- 访问严格按顺序操作(不可缓冲)。
- 外部外设区的后半段(0xC000_0000 - 0xDFFF_FFFF):
- 目前与前半段功能完全一致。
- 系统区(0xE000_0000 - 0xFFFF_FFFF):
- 用于私有外设和供应商指定功能区。
- 不可执行代码。
- 访问严格按顺序操作(不可缓存,不可缓冲)。
- 供应商指定功能区可以缓存和缓冲。
位操作带
Cortex-M3 处理器支持位带(bit-band)操作,允许对单一比特进行原子操作。位带操作仅适用于特定的存储器区域,包括 SRAM 区和片上外设区。
位带区和位带别名区
Cortex-M3 中有两个区域实现了位带操作:
- SRAM 区的最低 1MB 范围:
- 地址范围:0x2000_0000 - 0x200F_FFFF
- 对应的位带别名区:0x2200_0000 - 0x23FF_FFFF
- 片上外设区的最低 1MB 范围:
- 地址范围:0x4000_0000 - 0x400F_FFFF
- 对应的位带别名区:0x4200_0000 - 0x43FF_FFFF
位带别名区的映射
位带别名区将每个比特膨胀成一个 32 位的字。通过位带别名区访问这些字时,可以实现对原始比特的访问。具体映射关系如下:
- SRAM 区:
- 位带区地址:0x2000_0000 + (ByteOffset * 32) + (BitNumber * 4)
- 位带别名区地址:0x2200_0000 + (ByteOffset * 32) + (BitNumber * 4)
- 片上外设区:
- 位带区地址:0x4000_0000 + (ByteOffset * 32) + (BitNumber * 4)
- 位带别名区地址:0x4200_0000 + (ByteOffset * 32) + (BitNumber * 4)
其中:
-
ByteOffset
是位带区中字节的偏移量。 -
BitNumber
是字节中比特的编号(0-7)。公式推导
假设我们要访问 SRAM 区地址
A
处的第n
比特:- 计算字节偏移量:
ByteOffset
是位带区中字节的偏移量。ByteOffset = (A - 0x2000_0000)
- 计算比特偏移量:
BitNumber
是字节中比特的编号(0-7)。
- 计算位带别名区地址:
- 位带别名区地址 = 0x2200_0000 + (ByteOffset * 32) + (BitNumber * 4)
具体公式如下:
- SRAM 区:
AliasAddr = 0x2200_0000 + ((A - 0x2000_0000) * 32) + (n * 4)
- 片上外设区:
AliasAddr = 0x4200_0000 + ((A - 0x4000_0000) * 32) + (n * 4)
- 计算字节偏移量:
示例
假设我们要访问 SRAM 区地址 0x2000_0000 处的第 0 比特:
- 计算位带别名区地址:
- 位带区地址:0x2000_0000
- 位带别名区地址:0x2200_0000 + (0 * 32) + (0 * 4) = 0x2200_0000
- 访问位带别名区:
- 读取或写入地址 0x2200_0000 处的 32 位字,即可实现对原始比特的访问。
在 C 语言中使用位带操作
在 C 语言中,编译器并不直接支持位带操作。为了在 C 中使用位带操作,可以通过定义宏来实现。以下是具体的实现方法:
定义位带别名地址的宏
首先,定义一个宏来将“位带地址 + 位序号”转换成位带别名地址,并定义一个宏将该地址转换成指针类型。
// 把“位带地址 + 位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))
// 把该地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *) (addr))
解释
(addr & 0xF0000000)
:提取地址的高 4 位,用于确定位带区类型(SRAM 或片上外设区)。0x2000000
:位带别名区的基地址偏移量。((addr & 0xFFFFF) << 5)
:提取地址的低 20 位,并左移 5 位(相当于乘以 32),计算字节偏移量。(bitnum << 2)
:位序号左移 2 位(相当于乘以 4),计算比特偏移量
使用宏进行位带操作
使用上述宏,可以在 C 代码中进行位带操作。例如,假设我们要访问片上外设区地址 0x40000000
处的第 0 比特:
// 定义设备寄存器地址
#define DEVICE_REG0 ((volatile unsigned long *) (0x40000000))
// 使用正常地址访问寄存器
*DEVICE_REG0 = 0xAB;
// 使用位带别名地址设置 bit0
MEM_ADDR(BITBAND(DEVICE_REG0, 0)) = 0x1;
示例代码
以下是一个完整的示例代码,展示了如何在 C 语言中使用位带操作:
#include <stdio.h>
// 把“位带地址 + 位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))
// 把该地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *) (addr))
int main() {
// 定义设备寄存器地址
volatile unsigned long *DEVICE_REG0 = (volatile unsigned long *) (0x40000000);
// 使用正常地址访问寄存器
*DEVICE_REG0 = 0xAB;
// 使用位带别名地址设置 bit0
MEM_ADDR(BITBAND(DEVICE_REG0, 0)) = 0x1;
// 使用位带别名地址设置 bit1
MEM_ADDR(BITBAND(DEVICE_REG0, 1)) = 0x1;
// 读取寄存器值
unsigned long value = *DEVICE_REG0;
printf("Device Register Value: 0x%lx\n", value);
return 0;
}
互斥访问
在 Cortex-M3 处理器中,互斥访问(Exclusive Access)用于实现多任务环境中的共享资源保护。互斥访问通过 LDREX
和 STREX
指令对实现,确保对共享资源的访问是原子的,避免数据竞争和紊乱危象。
互斥访问的基本概念
互斥访问通过 LDREX
和 STREX
指令对实现,分别用于加载和存储操作。LDREX
指令用于加载数据并标记地址,STREX
指令用于存储数据并检查标记。只有当 STREX
指令的存储地址与 LDREX
指令标记的地址一致时,存储操作才会成功。
互斥访问的指令格式
-
LDREX:加载数据并标记地址。
LDREX Rxf, [Rn, #offset]
-
STREX:存储数据并检查标记。
STREX Rd, Rxf, [Rn, #offset]
互斥访问的工作原理
- LDREX:
- 加载数据到寄存器
Rxf
。 - 标记地址
(Rn + offset)
。
- 加载数据到寄存器
- STREX:
- 检查地址
(Rn + offset)
是否被标记。 - 如果地址被标记且没有其他存储操作(如
STR
或STREX
)在此期间执行,则存储数据到(Rn + offset)
,并将Rd
设置为 0。 - 如果地址未被标记或在此期间有其他存储操作执行,则存储操作被驳回,
Rd
设置为 1。
- 检查地址
互斥访问的优点
- 原子操作:确保对共享资源的访问是原子的,避免数据竞争。
- 避免紊乱危象:通过标记和检查机制,确保在多任务环境中共享资源的安全访问。
- 灵活性:适用于多任务环境和中断服务例程,保护共享资源不被多个任务同时访问。