各变量在MCU中的存放位置ram or flash

本文详细阐述了MCU中数据存储的三个主要位置:register、rom、ram,并介绍了标准C关键字和IAR预定义在MCU存储中的应用。

闲来无事,研究了下变量在MCU中存储位置
ps:MCU中能存放数据的地方有三处:register、rom、ram

涉及标准C关键字:register:定义和申请一个register级变量
                          auto::定义自动变量,缺省时为编译器默认
                          const:定义常量

涉及IAR预定义:   __no_init:说明变量不需初始化
                         section .text段:存放代码
                         section .rodata段:存放只读数据
                         section .noinit段:存放不需初始化数据
                         section .bss段:存放默认初始化数据
                         section .data段:存放已初始化数据
                         CSTACK段:栈
                         HEAP段:堆

//属性:宏变量
//位置:是在预编译期间被汇编进section .text段(一般放在rom里)
//操作:运行中已不存在
#define  ro_def   0x11111111UL

//属性:常量,只读变量
//位置:直接存在section .rodata段(一般放在rom里)
//操作:程序中访问时均是在section .rodata段中取(速度较慢)
const     uint32_t ro_var = 0x22222222;

//属性:未初始化全局变量
//位置:是存在section .noinit: DATA段(一般放在ram里)
//操作:程序中访问时均是在section .noinit: DATA段中存取(速度较快)
__no_init uint32_t ni_global_var;                 

//属性:默认0初始化全局变量
//位置:是存在section .bss段(一般放在ram里)
//操作:启动时将bss段清零;程序中访问时均是在section .bss段中存取(速度较快)
uint32_t zi_global_var;

//属性:已初始化全局变量
//位置:初始化值存在section .data_init段(一般放在rom里),变量本身是存在section .data段(一般放在ram里)
//操作:启动时将初值从.data_init段复制到.data段;程序中访问时均是在section .data段中存取(速度较快)
uint32_t i_global_var = 0x33333333; 

void test_variable(void) 
{
    //属性:已初始化寄存器变量
    //位置:其初始化值存在section .text段(一般放在rom里),变量本身存在cpu的register里
    //操作:如果申请成功,程序中访问时均是在cpu的register中存取(速度最快);如果申请失败,则是普通局部变量
    register  uint32_t i_register_var = 0x44444444;
    
    //属性:已初始化局部变量
    //位置:其初始化值存在section .rodata段(一般放在rom里),变量本身存在CSTACK里(一般放在ram里)
    //操作:定义时将初值从.rodata段复制到CSTACK中;程序中访问时均是在CSTACK段中存取(速度较快),一说局部变量入栈只是简单的移动SP指针,空出局部变量的位置而已.寻址是用SP的偏移量作为相对地址
    uint32_t i_local_iArray[4] = {0x55555555, 0x66666666, 0x77777777, 0x88888888};

    //属性:动态内存申请
    //位置:赋值是存在section .text段, 申请的内存区是存在HEAP里(一般放在ram里)
    //操作:程序中访问时均是在HEAP段中存取(速度较快)
    uint32_t *zi_local_p;
    p = (uint32_t *)malloc(4);

    ...
}
<think>嗯,用户想了解指令表地址与RAM地址之间的关系以及映射原理。这个问题涉及到计算机体系结构和微控制器设计的核心概念,需要从硬件和软件两个层面解释。用户可能正在学习STM32或其他嵌入式系统开发,遇到了地址映射相关的疑问。从提问的专业程度看,用户应该有一定基础,但可能对内存分区的具体实现机制不太清楚。需要特别注意用户提到的“指令表”这个表述——在嵌入式领域通常称为“向量表”或“中断向量表”。先梳理关键点:1)物理存储介质的差异(FlashvsRAM),2)地址空间的统一编址特性,3)启动阶段向量表的特殊处理。用户引用的资料提到STM32F103的寄存器映射,说明ta关注的是Cortex-M系列MCU的具体实现。需要强调几个易混淆概念:指令表本身存储在Flash中,但CPU执行指令时会通过总线将指令加载到指令缓存;中断向量表的初始位置固定,但运行时可以重定位到RAM。这个动态特性可能是用户困惑的点。在解释映射原理时,要区分ARM架构的通用设计(如固定地址0x00000000存放初始堆栈指针)和具体厂商的实现差异。用户提供的参考材料里GPIO寄存器映射的例子很好,可以类比说明外设寄存器的映射原理其实和向量表映射是同一机制的不同应用。最后生成的三个问题要层层递进:第一个问题确认基础概念,第二个深入启动流程的细节,第三个探讨实际应用场景。这样既能帮助用户自查理解程度,又覆盖了后续可能的知识延伸方向。</think>在 ARM Cortex-M 系列微控制器(如 STM32)中,**指令表地址(通常指中断向量表地址)与 RAM 地址**的关系及映射原理如下: --- ### **1. 核心关系** - **指令表(中断向量表)**:存储程序启动地址和中断服务函数入口地址的数组,通常位于 **Flash 存储器**的起始位置(默认地址 `0x0000 0000`)。 - **RAM 地址**:存储运行时变量、堆栈和动态数据的物理内存区域,地址范围通常从 `0x2000 0000` 开始。 - **关键映射**: 通过**内存重映射机制**,可将 Flash 中的中断向量表**复制到 RAM 中**,并将系统配置为从 RAM 地址读取中断向量。此时: ```c 原始中断向量表地址 (Flash) 0x0000 0000 → 重映射后的地址 (RAM) 0x2000 0000 ``` --- ### **2. 映射原理** #### **(1) 物理存储分离** | **存储类型** | **地址范围** | **内容** | |--------------|--------------------|-------------------------| | Flash | `0x0800 0000` 起 | 程序代码、初始中断向量表 | | RAM | `0x2000 0000` 起 | 运行时的数据、堆栈 | #### **(2) 地址重映射机制** - **启动阶段**:CPU 从 `0x0000 0000` 读取初始堆栈指针和复位向量(实际映射到 Flash 起始处 `0x0800 0000`)[^1]。 - **重映射操作**: 1. 将 Flash 中的中断向量表复制到 RAM(如 `0x2000 0000`)。 2. 配置系统控制寄存器 **`SCB->VTOR`**(向量表偏移寄存器),指向 RAM 中的新地址: ```c SCB->VTOR = 0x20000000; // 将中断向量表重定位至 RAM ``` 3. 此后发生中断时,CPU 直接访问 `0x2000 0000` 处的向量表[^2]。 #### **(3) 总线地址映射** - **统一编址原则**:FlashRAM、外设寄存器共享同一 4GB 地址空间,通过总线矩阵访问: ``` CPU → 总线矩阵 → { Flash, RAM, GPIO, UART, ... } ``` - **重映射本质**:修改 `VTOR` 寄存器,改变 CPU 查询中断向量的**目标地址基址**。 --- ### **3. 为何需要重映射?** 1. **加速中断响应**: RAM 的访问速度远快于 Flash,尤其需频繁修改向量表时(如动态加载固件)。 2. **动态更新中断服务函数**: 直接在 RAM 中修改向量表条目,无需擦写 Flash。 3. **降低中断延迟**: 避免 Flash 访问冲突(如执行代码时同时读取向量表)。 --- ### **4. 示例代码(STM32 重映射)** ```c #include "stm32f10x.h" // 定义 RAM 中的向量表位置 #define VECTOR_TABLE_RAM_BASE 0x20000000 int main(void) { // 1. 复制 Flash 向量表到 RAM uint32_t *vector_table_flash = (uint32_t*)0x08000000; // Flash 向量表起始地址 uint32_t *vector_table_ram = (uint32_t*)VECTOR_TABLE_RAM_BASE; for (int i = 0; i < 48; i++) { // 复制前 48 个向量(Cortex-M3) vector_table_ram[i] = vector_table_flash[i]; } // 2. 重定位向量表至 RAM SCB->VTOR = VECTOR_TABLE_RAM_BASE; // 3. 此后中断将使用 RAM 中的向量表 while (1); } ``` --- ### **
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值