Cortex-M3存储器系统

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(内存保护单元),可以通过它配置不同的存储区,并覆盖默认的访问属性。

存储器访问属性详解
  1. 可否缓冲(Bufferable)
    • 决定是否允许对存储器访问进行缓冲。缓冲可以提高访问速度,但可能导致数据不一致。
  2. 可否缓存(Cacheable)
    • 决定是否允许对存储器访问进行缓存。缓存可以提高访问速度,但可能导致数据不一致。
  3. 可否执行(Executable)
    • 决定是否允许在该存储区域执行指令。某些区域(如外设区)不允许执行指令。
  4. 可否共享(Sharable)
    • 决定是否允许在多核系统中共享该存储区域。共享区域需要严格按顺序操作,以确保数据一致性。
存储器区域划分

Cortex-M3 的地址空间分为 8 个 512MB 等份,每个区域具有不同的访问属性:

  1. 代码区(0x0000_0000 - 0x1FFF_FFFF)
    • 可执行指令。
    • 缓存属性为 WT(写通,Write Through),不可缓存。
    • 数据操作通过数据总线接口(读数据使用 D-Code,写数据使用 System)。
    • 写操作是缓冲的。
  2. SRAM 区(0x2000_0000 - 0x3FFF_FFFF)
    • 用于片内 SRAM。
    • 写操作是缓冲的。
    • 可以选择 WB-WA(写回,Write Back,写分配,Write Allocated)缓存属性。
    • 可执行指令,允许将代码拷贝到内存中执行。
  3. 片上外设区(0x4000_0000 - 0x5FFF_FFFF)
    • 用于片上外设。
    • 不可缓存,不可执行指令(XN,eXecute Never)。
  4. 外部 RAM 区的前半段(0x6000_0000 - 0x7FFF_FFFF)
    • 用于片外 RAM。
    • 可缓存(缓存属性为 WB-WA),可执行指令。
  5. 外部 RAM 区的后半段(0x8000_0000 - 0x9FFF_FFFF)
    • 除了不可缓存(WT)外,同前半段。
  6. 外部外设区的前半段(0xA000_0000 - 0xBFFF_FFFF)
    • 用于片外外设的寄存器和多核系统中的共享内存。
    • 不可缓存,不可执行指令。
    • 访问严格按顺序操作(不可缓冲)。
  7. 外部外设区的后半段(0xC000_0000 - 0xDFFF_FFFF)
    • 目前与前半段功能完全一致。
  8. 系统区(0xE000_0000 - 0xFFFF_FFFF)
    • 用于私有外设和供应商指定功能区。
    • 不可执行代码。
    • 访问严格按顺序操作(不可缓存,不可缓冲)。
    • 供应商指定功能区可以缓存和缓冲。

位操作带

Cortex-M3 处理器支持位带(bit-band)操作,允许对单一比特进行原子操作。位带操作仅适用于特定的存储器区域,包括 SRAM 区和片上外设区。

位带区和位带别名区

Cortex-M3 中有两个区域实现了位带操作:

  1. SRAM 区的最低 1MB 范围
    • 地址范围:0x2000_0000 - 0x200F_FFFF
    • 对应的位带别名区:0x2200_0000 - 0x23FF_FFFF
  2. 片上外设区的最低 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 比特:

    1. 计算字节偏移量
      • ByteOffset 是位带区中字节的偏移量。
      • ByteOffset = (A - 0x2000_0000)
    2. 计算比特偏移量
      • BitNumber 是字节中比特的编号(0-7)。
    3. 计算位带别名区地址
      • 位带别名区地址 = 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 比特:

  1. 计算位带别名区地址
    • 位带区地址:0x2000_0000
    • 位带别名区地址:0x2200_0000 + (0 * 32) + (0 * 4) = 0x2200_0000
  2. 访问位带别名区
    • 读取或写入地址 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)用于实现多任务环境中的共享资源保护。互斥访问通过 LDREXSTREX 指令对实现,确保对共享资源的访问是原子的,避免数据竞争和紊乱危象。

互斥访问的基本概念

互斥访问通过 LDREXSTREX 指令对实现,分别用于加载和存储操作。LDREX 指令用于加载数据并标记地址,STREX 指令用于存储数据并检查标记。只有当 STREX 指令的存储地址与 LDREX 指令标记的地址一致时,存储操作才会成功。

互斥访问的指令格式
  • LDREX:加载数据并标记地址。

    LDREX Rxf, [Rn, #offset]
    
  • STREX:存储数据并检查标记。

    STREX Rd, Rxf, [Rn, #offset]
    
互斥访问的工作原理
  1. LDREX
    • 加载数据到寄存器 Rxf
    • 标记地址 (Rn + offset)
  2. STREX
    • 检查地址 (Rn + offset) 是否被标记。
    • 如果地址被标记且没有其他存储操作(如 STRSTREX)在此期间执行,则存储数据到 (Rn + offset),并将 Rd 设置为 0。
    • 如果地址未被标记或在此期间有其他存储操作执行,则存储操作被驳回,Rd 设置为 1。
互斥访问的优点
  • 原子操作:确保对共享资源的访问是原子的,避免数据竞争。
  • 避免紊乱危象:通过标记和检查机制,确保在多任务环境中共享资源的安全访问。
  • 灵活性:适用于多任务环境和中断服务例程,保护共享资源不被多个任务同时访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值