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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


闲来无事,研究了下变量在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);

    ...
}
### STM32CubeMX 中 USER_VECT_TAB_ADDRESS 的配置与使用 在 STM32 微控制器开发过程中,`USER_VectTabAddress` 是一个重要的参数,用于指定向量表的位置。这通常涉及到外部存储器映射或者内部 SRAM/Flash 配置的情况。 #### 向量表的概念 中断向量表是一个包含所有异常处理程序和中断服务例程入口地址的数组。默认情况下,STM32 的中断向量表位于 Flash 存储器的起始位置 (通常是 `0x08000000`)。然而,在某些应用场景下(例如双核启动、外扩 RAM 使用等),可能需要将向量表重新定位到其他内存区域[^1]。 #### 如何设置 USER_VectTabAddress? 当通过 STM32CubeMX 工具生成项目时,可以在 **Clock Configuration** 页面找到关于 `USER_VectTabAddress` 的选项: 1. 打开 STM32CubeMX 并加载目标 MCU 型号。 2. 进入 **System Core -> RCC** 设置界面。 3. 查找并勾选 **Vector Table Relocation in Internal FLASH/SRAM** 选项。 4. 输入具体的重定向地址至变量 `__Vectors` 或者自定义名称下的偏移值。 此操作会修改初始化代码中的 SCB->VTOR 寄存器指向新的基址,从而允许处理器从此处获取中断矢量信息而不是默认闪存起点[^2]。 #### 实际应用案例分析 假设我们需要把应用程序下载到片上 SRAM 而不是常规 flash 上运行,则必须调整向量表使其匹配当前执行环境的需求。以下是典型做法之一: ```c // 将向量表复制到SRAM中 void SystemInit(void){ uint32_t *src, *dst; src = (__IO uint32_t*)VECT_TAB_FLASH; // 定义源地址为flash上的原始向量表 dst = (__IO uint32_t*)SRAM_BASE_ADDR; // 目的地设为我们希望使用的sram首部 /* Copy the vector table */ for(int i=0;i<NUM_OF_VEC_ENTRIES;i++) { *(dst+i) = *(src+i); } SCB->VTOR = SRAM_BASE_ADDR | VECT_TAB_OFFSET; // 更新SCB VTOR寄存器完成切换 } ``` 上述片段展示了如何手动迁移原生 ROM 内容到 RAM 当前可用区间,并同步更新 CPU 控制单元以识别更改后的布局结构. #### 注意事项 - 如果计划改变向量表的实际物理存放地点,请务必确认新选址具备足够的空间容纳整个表格以及后续扩展可能性。 - 对于低功耗模式设计而言,动态管理该属性可能会带来额外复杂度,需谨慎评估利弊得失后再决定实施策略。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值