STM32 堆栈空间分布

参考

  1. 运行时访问__initial_sp__heap_base

无RTOS时的情况

在这里插入图片描述
在以上配置的情况下,生成工程。在工程的startup.s文件中,由如下代码:

Stack_Size		EQU     0x400AREA    STACK, NOINIT, READWRITE, ALIGN=3
__Stack_top		; 自己添加
Stack_Mem       SPACE   Stack_Size
__initial_spIF      :DEF:__MICROLIB           EXPORT  __initial_spEXPORT  __heap_baseEXPORT  __heap_limitEXPORT  __Stack_top	; 自己添加
ELSEIMPORT  __use_two_region_memoryEXPORT  __user_initial_stackheap
__user_initial_stackheapLDR     R0, =  Heap_MemLDR     R1, =(Stack_Mem + Stack_Size)LDR     R2, = (Heap_Mem +  Heap_Size)LDR     R3, = Stack_MemBX      LRALIGN
ENDIF

通过以上代码可以看出,需要使能MicroLib才会默认导出__initial_sp,__Stack_top,__heap_base,__heap_limit这几个变量。(如果不使能MicroLib,则需要在上面代码的ELSE下面也添加EXPORT语句将这几个变量导出)。
然后在main.c中添加如下代码,查看以上这些变量的值:

  extern uint32_t __heap_base, __heap_limit;extern uint32_t __Stack_top, __initial_sp;extern uint32_t __Vectors, __Vectors_End, __Vectors_Size;while (1){// 0x200013A8 ~ 0x200015A8  size:0x200  RAMprintf("heapS[0x%08x], heapE[0x%08x]\r\n", (uint32_t)&__heap_base, (uint32_t)&__heap_limit);// 0x200019A8 ~ 0x200015A8  size:0x400  RAMprintf("stackS[0x%08x], stackE[0x%08x]\r\n", (uint32_t)&__initial_sp, (uint32_t)&__Stack_top); // 0x08000000 ~ 0x080000EC  ROMprintf("VectS[0x%08x], VectE[0x%08x], VectSize[0x%x]\r\n\r\n", (uint32_t)&__Vectors, (uint32_t)&__Vectors_End, (uint32_t)&__Vectors_Size);}

从上可以看到,__Stack_top__heap_limit是一样的,说明这里分配的堆和栈是紧邻的。而且地址刚好也和我们在cubeMx中定义的一致。堆和栈是在RAM中,而中断向量表是在Flash中。

添加FreeRTOS

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从以上三张图中,可以发现,我们给FreeRTOS总共分配了3072(0xC00) Bytes HEAP空间。而我们定义了一个defaultTask并分配了256 * 4 = 1024 Bytes,但是在最后的FreeRTOS Heap Usage页面看到,defaultTask实际使用了1144 Bytes,剩余3072 - 1144 = 1928 Bytes。(除了defaultTask多使用的1144 - 1024 = 120 Bytes(用于任务控制块TCB)外,其余都是可以对上的。)
生成工程后,我们还是将之前的那些堆栈指针地址打印出来,看一下MCU是如何进行地址分配的。只是这里还需要添加FreeRTOS中的堆栈信息了。首先通过追踪configTOTAL_HEAP_SIZE可以发现,堆空间定义为了一个数组:

	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];uint8_t* osHeapPoint = ucHeap;		// 由于以上变量是 static 类型,所有这里再定义一个指针指向这个 Heap 地址,以便在外部访问它;

然后我们就可以在defaultTask任务里面添加输出以上变量地址的代码了:

  extern uint32_t __heap_base, __heap_limit;extern uint32_t __Stack_top, __initial_sp;extern uint32_t __Vectors, __Vectors_End, __Vectors_Size;extern uint8_t* osHeapPoint;extern uint32_t local_addr1, local_addr2;void* os_mal_buf = malloc(50);uint32_t tast_local_val = 1;for(;;) {// 0x20002D10 ~ 0x20002F10  size:0x200  RAMprintf("HeapS[0x%08x], HeapE[0x%08x]\r\n", (uint32_t)&__heap_base, (uint32_t)&__heap_limit);// 0x20003310 ~ 0x20002F10  size:0x400  RAMprintf("StackS[0x%08x], StackE[0x%08x]\r\n", (uint32_t)&__initial_sp, (uint32_t)&__Stack_top);	// // 0x08000000 ~ 0x080000EC  ROMprintf("VectS[0x%08x], VectE[0x%08x], VectSize[0x%x]\r\n", (uint32_t)&__Vectors, (uint32_t)&__Vectors_End, (uint32_t)&__Vectors_Size);		// 中断向量表// 0x20002110   size: 3072 Bytes(0xC00)printf("OsHeapPoint[0x%08x]\r\n", (uint32_t)osHeapPoint);	// freeRTOS中定义的HEAP数组// 0x20002D18printf("Os_mal_buf[0x%08x]\r\n", (uint32_t)os_mal_buf);// 0x20002504printf("&Os_mal_buf[0x%08x]\r\n", (uint32_t)&os_mal_buf);// 0x20002508printf((char*)buf, "&tast_local_val[0x%08x]\r\n\r\n", (uint32_t)&tast_local_val);	// 在freeRTOS任务中定义的局部变量// 0x20000008, 0x2000000Cprintf("&global_var1[0x%08x], &global_var2[0x%08x]\r\n", (uint32_t)&global_var1, (uint32_t)&global_var2);	// 函数外部定义的全局变量// 0x20003304, 0x20003308printf("local_addr1[0x%08x], local_addr2[0x%08x]\r\n\r\n", local_addr1, local_addr2);	// 这两个全局变量保存了在freeRTOS初始化前,在main()函数中定义的两个局部变量的地址}

根据以上输出总结如下:
在这里插入图片描述

  1. local_addr的地址(靠近__initial_sp)可以看出,栈空间的地址值是向下增长的,即栈顶(__initial_sp = 0x20003310)在高地址;
  2. 从全局变量的地址可以看出,全局变量是默认分配在RAM的起始地址;
  3. freeRTOS任务中定义的局部变量(&tast_local_val = 0x20002508)存储在定义freeRTOS时定义的HEAP里(0x20002110~0x20002D10);
  4. 再看一下&tast_local_val = 0x20002508这个数据,发现0x20002508大概等于0x20002110 + 256*4 = 0x20002510。这就再次说明,freeRTOS定义任务时,是从配置好的HEAP地址初始空间的开始部分给新任务分配Task stack的,而在任务中使用这个task stack时,还是符合栈的使用规范(即从高地址开始分配);
  5. s_mal_buf = 0x20002D18可以知道,即使在freeRTOS任务中动态分配,也是在任务之外的堆中分配空间。

疑问

  1. 通过以上总结,发现在freeRTOS任务中定义局部变量和在freeRTOS任务之外定义局部变量,他们分配的地址空间是不一样的。那么,如果有以下函数:
void addr_test(void)
{uint32_t loc_var = 1;printf("&loc_var = 0x%08x\r\n", (uint32_t)&loc_var);
}

我分别在freeRTOS初始化之前调用,以及在freeRTOS的任务中调用,其输出会是什么呢?
经过验证,在freeRTOS初始化之前调用,输出的地址范围在0x20002F10 - 0x20003310之间;而在freeRTOS的任务中调用,输出的地址范围在0x20002110 - 0x20002D10之间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/137423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ResourceQuota对象在K8s上的说明

ResourceQuota资源对象的说明,以及在集群中的作用说明 定义说明 https://kubernetes.io/zh-cn/docs/concepts/policy/resource-quotas/ 集群中的资源组的划分和设计 在具有 32 GiB 内存和 16 核 CPU 资源的集群中,允许 A 团队使用 20 GiB 内存 和 10 核…

完全零基础,教你创建数码配件小程序商城

现如今,随着数码产品的普及,数码配件市场也越来越火爆。如果你有兴趣进入这个行业,并且想要开设一家数码配件小程序商城,那么不要担心,即使你完全零基础也可以轻松实现。 首先,登录【乔拓云】网后台&#x…

城市内涝积水监测,万宾科技内涝预警监测系统

每一个城市的排水体系都是一个复杂的网络系统,需要多个部分配合协调,预防城市排水管网带来安全隐患,也因此才能在一定程度上缓解城市内涝带来的安全问题。在海绵城市建设过程中不仅要解决大部分道路硬化导致的积水无法渗透等问题,…

【架构】后端项目经典分层架构介绍

文章目录 前言分层架构项目实践示例项目结构 其他知识 前言 开发后端项目时,我们最常见的一种架构模式就是分层架构 。 所谓的分层架构,就是把系统自上而下分为多个不同的层,每一层都有特定的功能和职责,且只和自己的直接上层与…

小白学爬虫:通过商品ID或商品链接封装接口获取淘宝商品销量数据接口|淘宝商品销量接口|淘宝月销量接口|淘宝总销量接口

淘宝商品销量接口是淘宝开放平台提供的一种API接口,通过该接口,商家可以获取到淘宝平台上的商品销量数据。使用淘宝商品销量接口的步骤如下: 1、在淘宝开放平台注册并创建应用,获取API Key和Secret Key等必要的信息。 2、根据淘宝…

【Vue】【uni-app】工单管理页面实现

用的是uni-app的uni-ui拓展组件实现的 功能是对工单进行一个展示,并对工单根据一些筛选条件进行搜索 目前是实现了除了日期之外的搜索功能,测试数据是下面这个tableData.js,都是我自己手写的,后端请求也稍微写了一些,…

View 自定义 - 属性 Attribute

一、概念 在 xml 中为控件设置的属性。自定义属性名称如果使用系统已定义的&#xff0c;例如 textSize 会在编译时报错。 格式类型定义/使用 string 字符串 <attr name "myContent" format "color" /> android:myContent "Hello Word!&quo…

FPGA配置采集AR0135工业相机,提供2套工程源码和技术支持

目录 1、前言免责声明 2、AR0135工业相机简介3、我这里已有的 FPGA 图像处理解决方案4、设计思路框架AR0135配置和采集图像缓存视频输出 5、vivado工程1–>Kintex7开发板工程6、vivado工程1–>Zynq7100开发板工程7、上板调试验证8、福利&#xff1a;工程代码的获取 1、前…

Java多线程3种中断方式和终止方式

一、线程中断 Java 中有以3 种方法可以中断正在运行的线程&#xff1a; 使用&#xff08;volatile修饰&#xff09;退出标志&#xff0c;使线程正常退出&#xff0c;也就是当 run() 方法完成后线程中止&#xff1b;也可使用 Atomic 变量作为退出标志&#xff0c;同样可以实现…

水仙花数-C语言和python实现

C语言代码 #include<stdio.h>int main(){int i100,j0;int count0;int num0;for (; i < 1000; i){count i;for(;j<3;j){num num (count%10)*(count%10)*(count%10);count (int)(count/10);}if (numi){/* code */printf("%d是一个水仙花数\n",num);nu…

【解决问题】---- 解决 avue-crud 表格勾选数据翻页后界面保持选中

1. 错误预览 第一页选择【7、8、9、10】 直接点击第三页未进行选择 直接点击第四页未进行选择 2. 问题总结 通过测试可以看到&#xff0c;页面的选择项会影响到其他页面的选择&#xff1b;点击保存&#xff0c;返回的数据却是真真选择的数据&#xff1b;数据在选择渲染…

【论文阅读】多模态NeRF:Cross-Spectral Neural Radiance Fields

https://cvlab-unibo.github.io/xnerf-web intro 从不同的light spectrum sensitivity获取信息&#xff0c;同时需要obtain a unified Cross-Spectral scene representation – allowing for querying, for any single point, any of the information sensed across spectra。…

@Autowired注入其他模块的bean失败

一、在Spring Boot中&#xff0c;如果要自动扫描和创建bean&#xff0c;需要在应用的启动类上使用ComponentScan注解来指定要扫描的包。确保你已经将GlobalConfig类所在的包和父包都添加到了ComponentScan注解的value属性中。 例如&#xff0c;如果GlobalConfig类所在的包为com…

CAN轴【禾川】

禾川CAN轴有问题。 厂家说是只能使用禾川的伺服X2EN&#xff0c;和X3EN 添加CAN主站&#xff1a; 网络&#xff1a; 0 波特率&#xff1a; 1000K 添加CAN总线&#xff1a; 主站&#xff1a; 2 同步帧&#xff1a; 80h 设置刷新时间 时间帧&#xff1a;100h 添加伺服&…

Vue el-table序号与复选框hover切换

效果图下&#xff1a; <template><div class"container"><el-tableref"multipleTable"id"multipleTable":data"person.tableData"cell-mouse-enter"cellEnter"cell-mouse-leave"cellLeave"selecti…

VSCode remote-ssh 连接远端服务器失败

系统 Mac os Intel处理器 描述 该问题在上午时还没有&#xff0c;下午突然毫无征兆的发生&#xff0c;当时没有更新vscode&#xff0c;没有更新插件。 分析 网上对于该问题的答案多是说磁盘空间不够vscode不能下载相应插件&#xff0c;我所遇到的并不是这种情况。报的错误多是…

Leetcode-LCR 021 删除链表的倒数第 N 个结点

快慢指针&#xff0c;快指针先移动n-1个节点后&#xff0c;慢指针从虚拟头结点出发&#xff08;相当于快慢指针相隔n个节点&#xff09;&#xff0c;快慢指针一起向链表尾依次移动一个结点&#xff0c;当快指针移动到表位时&#xff0c;慢指针正好移到被删除元素的前一个结点&a…

基于$indexStats 构建mongodb 所有集合的索引监控程序

使用mongodb时&#xff0c;为集合中经常查询的字段添加索引&#xff0c;能够提高查询效率&#xff0c;减少扫描数据次数&#xff0c;限制扫描数据量&#xff0c;减少排序时间和内存与CPU的消耗。但索引的更新会为数据的添加和更新带来额外的消耗。因此&#xff0c;需要定期检查…

Python数据容器(字符串)

字符串 1.字符串 字符串也是数据容器的一种&#xff0c;字符串是字符的容器&#xff0c;一个字符串可以存放任意数量的字符。 2.字符串的下标索引 从前向后&#xff0c;下标从0开始从后向前&#xff0c;下标从-1开始 # 通过下标索引获取特定位置的字符 name python print(na…

关于使用template时的错误注意

今天在写c程序的时候&#xff0c;在使用template时遇到了一个关于template的错误用法。代码如下#include <vector> #include <algorithm> #include <forward_list> #include <string> #include <list> using namespace std; template <typena…