• 【嵌入式】堆栈与单片机内存


    堆栈

    在片内RAM中,常常要指定一个专门的区域来存放某些特别的数据
    它遵循顺序存取和后进先出(LIFO/FILO)的原则,这个RAM区叫堆栈。

    其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。

    堆栈特点

    1、这些存储单元中的内容都是程序执行过程中被中断打断时,事故现场的一些相关参数。如果不保存这些参数,单片机执行完中断函数后就无法回到主程序继续执行了。

    2、这些存储单元的地址被记在了一个叫做堆栈指针(SP)的地方。
    3、栈是从高到低分配,堆是从低到高分配。

    堆栈分类

    我们一般说的堆栈指的栈。堆栈又分硬堆栈和软堆栈,硬堆栈即SP,从片内RAM的顶部向下生长。软堆栈在硬堆栈跟全局变量区之间的空间,C51函数调用通过R0-R7和栈来实现。

    堆栈作用

    1)子程序调用和中断服务时CPU自动将当前PC值压栈保存,返回时自
    动将PC值弹栈。
    2)保护现场/恢复现场
    3)数据传输

    单片机内存

    程序内存可以分为几个区,栈区(stack),堆区(Heap),全局区(static),文字常亮区,程序代码区。
    在这里插入图片描述

    //main.cpp
    int a = 0; //全局初始化区
    int a = 0; //全局初始化区
    char *p1; //全局未初始化区
    main() {
        int b; //栈
        char s[] = "abc"; //栈
        char *p2; //栈
        char *p3 = "123456"; //123456\0在常量区,p3在栈上。
        static int c = 0; //全局(静态)初始化区
        p1 = (char *)malloc(10);
        p2 = (char *)malloc(20);
        //分配得来得10和20字节的区域就在堆区。
        strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    和栈的第一个区别就是申请方式不同:栈(英文名称是stack)是系统自动分配空间的,例如我们定义一个 char a;系统会自动在栈上为其开辟空间。而堆(英文名称是heap)则是程序员根据需要自己申请的空间,例如malloc(10);开辟十个字节的空间。由于栈上的空间是自动分配自动回收的,所以栈上的数据的生存周期只是在函数的运行过程中,运行后就释放掉,不可以再访问。而堆上的数据只要程序员不释放空间,就一直可以访问到,不过缺点是一旦忘记释放会造成内存泄露。

    STM32

    在MDK编译环境下,可在map文件的"Memory Map of the image"–>"Execution Region RW_IRAM1"内容中查看程序的RAM占用及分配情况,如下:
    在这里插入图片描述

    STM32程序数据分类

    Code:程序代码
    RO-data:const常量和指令
    RW-data:初始化值不为0的全局变量
    ZI-data:未初始化的全局变量 或 初始化值为0的全局变量

    RO Size = Code + RO Data 表示程序运行时占用的FLASH大小
    RW Size = RW Data + ZI Data 表示占用RAM大小
    ROM Size = Code + RO Data + RW Data 表示烧写程序后占用的FLASH大小

    STM32内存(RAM)分配

    一个由C/C ++编译的程序占用的内存可分为以下几个部分:

    栈(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等。
    堆(heap):存放程序运行中被动态分配的内存,一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
    bss段:通常是指用来存放程序中未初始化的全局变量的一块内存区域,存放ZI-data数据
    data段:通常是指用来存放程序中已初始化的全局变量的一块内存区域,存放RW-data数据

    FLASH占用大致以下两个部分:

    文字常量区(const) :常量字符串就是放在这里的。
    程序代码区 (code): 存放函数体的二进制代码

    STM32堆栈位置

    在这里插入图片描述
    STM32的堆栈就是存放在片上静态SRAM中的.
    在这里插入图片描述
    地址分配可以见Keil的编译map文件的"Memory Map of the image"
    可见堆的地址为0x20000a08,大小为0x200,栈的地址为 0x20000c08,大小为0x400,可推算栈顶地址为:0x20000c08 + 0x400 = 0x20001008。而程序在刚运行的时候,主堆栈指针MSP指向的是程序所占用内存的最高地址,也就是栈的栈顶地址MSP,也就是中断向量表前四个字节存储的值。
    在这里插入图片描述

  • 相关阅读:
    Git同时配置和提交代码到Github和Gitee
    5分钟了解二叉树之LeetCode里的二叉树
    Day11: 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和 222.完全二叉树的节点个数
    Linux 环境删除Conda
    03【BIO编程】
    Spring Boot实现任意位置的properties及yml文件内容配置与获取
    FinOps for Kubernetes - 如何拆分 Kubernetes 成本
    基于SOCKET编程多人聊天软件HTML+JSON报文
    docker mysql 主从配置
    题目新颖,内容全面!阿里巴巴又一 Java 面试神册开源!
  • 原文地址:https://blog.csdn.net/apythonlearner/article/details/133791607