stm32以及freertos 堆栈解析

这篇具有很好参考价值的文章主要介绍了stm32以及freertos 堆栈解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

以前在mcu编程的时候没有太注意堆栈的情况,只知道需要将堆栈设置的大一点。现在逐步使用freertos,在freertos中也有关于堆栈的设置,freertos的堆栈和启动文件中的堆栈关系是什么?为了以后使用的无误,本次一次性把这些弄清楚。


1、定义

堆栈是一个特定的存储区或者寄存器。一般在内存总开辟一块区域作为堆栈,叫做软件堆栈;用寄存器构成的堆栈,叫硬件堆栈。大多数情况下,我们使用的都是软件堆栈。

stm32以及freertos 堆栈解析
在stm或者gd32的启动文件中的堆栈就是软件堆栈。

堆栈中数据的存储,都要遵循先进后出的原则,可以类比为木桶,先放进去的数据在桶的底部,后放进去的数据在桶的顶部。取数据的时候是先在桶的顶部取数据,在从桶的底部取数据。

单片机应用中,堆栈是个特殊存储区,堆栈属于RAM空间的一部分,堆栈用于函数调用、中断切换时保存和恢复现场数据。堆栈中的物体具有一个特性:第一个放入堆栈中的物体总是被最后拿出来, 这个特性通常称为先进后出 (FILO—First-In/Last-Out)。 堆栈中定义了一些操作, 两个最重要的是PUSH和POP。 PUSH(入栈)操作:堆栈指针(SP)加1,然后在堆栈的顶部加入一 个元素。POP(出栈)操作相反,出栈则先将SP所指示的内部ram单元中内容送入直接地址寻址的单元中(目的位置),然后再将堆栈指针(SP)减1。这两种操作实现了数据项的插入和删除。

关于堆栈的理论知识就简述这么多,部分来自于百度百科。在mcu中我们只要知道上图设置的堆栈实际是位于mcu的ram区就可以了。在mcu编程中,貌似对ram的关注都不多,更多的是关注flash的容量,falsh大小能不能存储的了我的固件之类的。对ram就没有知道有这个东西,但真没有细致关注。

2、堆栈的空间分配

在mcu中,heap和stack的使用者是不同的。
stack(栈):由系统自动分配释放,存放的函数的参数值,局部变量的值。这个空间用户操作不了的。

heap(堆):由用户分配及释放,也就是调用malloc 和free,时操作的空间就是堆空间。

站原子论坛上,建议,如果没有调用系统的malloc和free函数,heap空间可以设置为0.

从空间分配上,最好理解的就是heap,完全由用户操作。比较难理解的是stack,那么系统到底是怎么使用的栈空间的呢。

3、stm32栈空间及编译的固件大小

用keil编译工程完成后,output窗口会显示如下信息:
stm32以及freertos 堆栈解析
上图的中的code ro-data rw-data zi-data是什么意思,哪些是站ram空间,哪些是站flash空间呢?在上文中我们说到stack是有系统自动分配的,那么我把启动文件中的stack_size改变一下,再看下编译输出结果。
stm32以及freertos 堆栈解析
将stack_size 由0x2000改为0x1000,有8k字节改为4k字节。编译后的结果如下图。

stm32以及freertos 堆栈解析
与上一次的编译对比发现,只有zi-data段变化了由10508变成了6412.二者的差值刚好是4096,就是stack_size的减少值。

在将heap_size设置为0x1000,发现编译出来的没有任何变化。

3.1 存储数据段

Code是代码占用的空间;

RO-data是 Read Only 只读常量的大小,如const型;

RW-data是(Read Write) 初始化了的可读写变量的大小;

ZI-data是(Zero Initialize) 没有初始化的可读写变量的大小。

最终,烧写时flash被占有的空间为:

falsh = Code + RO-Data + RW-Data

程序运行时ram被占有的空间为

ram = RW-Data + ZI-Data

计算一下falsh占有空间 = 12568+ 368+ 180 = 13116字节
stm32以及freertos 堆栈解析
看下最终生成的bin文件刚好是13116字节大小。

找到了flash占用的空间,我们再来看看ram占用的空间。ram占用空间在生成的.map文件中。
stm32以及freertos 堆栈解析
map文件中显示ram占用的size为0x19c0,转换为10进制为6592,而生成RW-Data + ZI-Data=180+6412=6592.这个也得到了验证。

根据上面的图还可以得出:

** RW-Data= .data** data的空间累加即为RW-Data
** ZI-Data= .bss+STACK** .bss的空间累加+STACK即为ZI-Data

上图中也可以看出STACK=0x1000刚好是在启动文件中设定的值。也可以看出当前芯片的ram总空间为0x18000=96kB。

到这里我们基本梳理出来的ram和falsh空间的构成。接下来看看freertos的堆栈是啥。

3.2freertos堆栈

我使用的是freertos是v10版本,内存分配采用的heap4.c
在freertos的FreeRTOSConfig.h中,需要设置堆的大小

#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 1 * 1024 ) )

这里做测试我就只设置为1024字节。全局搜索下configTOTAL_HEAP_SIZE ,发现是在heap_4.c中使用了。
stm32以及freertos 堆栈解析
按照当前的设置可以看到,freertos是直接定义了一个静态数组 hcHeap大小为configTOTAL_HEAP_SIZE。

configAPPLICATION_ALLOCATED_HEAP这个宏定义一般是将堆设置为外部sram才会用到。这里暂时不多讲。

从上图可以得出这样的结论,默认情况下,freertos的堆就是自定义的一个大型数组,与启动文件中设置heap_size没有任何关系。所以只要只要没有调用系统的malloc函数,启动文件heap_size还真可以设置为0.

接下来,将configTOTAL_HEAP_SIZE改成20Kb进行编译。结果如下
stm32以及freertos 堆栈解析
zi-data由6142变成了25868,二者差值刚好是19kB。编译后的map文件内容如下:

stm32以及freertos 堆栈解析
与上一次的对比,.bss段的heap_4.o占用的空间由0x400(1kB)变成了0x5000(20kB),刚好是configTOTAL_HEAP_SIZE宏定义设定的大小。

4、结论

经过了上面的实验分析可以得出如下结论:

  1. 当freertos采用heap_4内存分配方案时,stm32启动文件中的stack_size 和heap_size与freertos中设置的堆大小没有任何关系。
  2. 只要代码中没有使用系统malloc函数,启动文件heap_size可以设置为0
  3. mcu运行时的ram空间= RW-Data+ZI-Data+启动文件中的heap_size,所以可以根据这个公式来设置freertos堆的大小。freertos的堆尽量要设置的大一点。

5、freertos堆常用函数heap_4

stm32以及freertos 堆栈解析
上还是那个图来自freertos的官方文档,可以看出freertos的栈实际实际上也是放到了堆空间。任务控制块TCB、queue 、pvPortMalloc等使用都是堆空间,对空间大小有configTOTAL_HEAP_SIZE决定。

5.1常用heap相关函数

获取剩余heap空间大小。

size_t xPortGetFreeHeapSize( void );

获取最小未分配的空间大小

size_t xPortGetMinimumEverFreeHeapSize( void );

动态内存分配及释放函数

void * pvPortMalloc( size_t xWantedSize )
void vPortFree( void * pv )

5.2任务栈空间占用的大小。

freertos中每个任务新建的时候都要设置栈空间。栈空间可以在FreeRTOSConfig.h中设定一个最小值

#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 128 )  //设置最小栈空间为256字节

记住这里设定的和任务新建时设定的大小单位并不是字节,而是字,字占4个字节,所以上述设定的最小栈空间为256字节。由上文可知,freertos的栈空间实际是在堆里面。

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )

pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) )

 #define pvPortMallocStack    pvPortMalloc

在新建任务函数中,可以看到,实际上使用pvPortMalloc分配的一段空间作为栈空间,大小为usStackDepth *sizeof( StackType_t ) 。而StackType_t 大小实际上是uint32_t 为4字节。

stm32以及freertos 堆栈解析文章来源地址https://www.toymoban.com/news/detail-401125.html

到了这里,关于stm32以及freertos 堆栈解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FreeRTOS学习之路,以STM32F103C8T6为实验MCU(序章——浅谈单片机以及FreeRTOS)

    学习之路主要为FreeRTOS操作系统在STM32F103(STM32F103C8T6)上的运用,采用的是标准库编程的方式,使用的IDE为KEIL5。 注意!!!本学习之路可以通过购买STM32最小系统板以及部分配件的方式进行学习,也可以通过Proteus仿真的方式进行学习。 后续文章会同时发表在个人博客(jaso

    2024年02月06日
    浏览(54)
  • 基于STM32的homeassistant(采用FreeRTOS操作系统)【第一、二章优化拓展:Wifi、服务器连接验证以及UASRT串口区分】

      主控 STM32F103C8T6 WIFI模块 ESP01S 开发语言 C 开发编译器· KEIL 组网方式 WIFI 服务器协议 MQTT STM32 ESP01S 3.3V 3.3V GND GND GPIO2  (USRAT2-TX) RX GPIO3 (USART3-RX) TX 对ESP01S的AT指令的反馈指令进行验证解析 对ESP的USART2通信串口进行printf端口重映射 对调试用的USART1通信串口编写USART_printf函数并

    2024年02月17日
    浏览(50)
  • STM32堆栈方面知识点

    最近弄json,发现经常的堆溢出,然后找问题。因为对STM32堆栈问题没有深刻认识,就花时间好好研究下了堆栈并且做了验证 1.栈地址区间确定 首先找到启动文件,我的启动文件在startup_stm32f40xx.s,一般的启动文件也都在startup_stm32fxxxx.s文件里 __initial_sp      这个参数是栈顶地

    2024年02月10日
    浏览(34)
  • STM32基于HAL解析GPS经度纬度以及时间

    第一步:打开CubeMX工具: 第二步:创建一个工程:搜索一下需要的芯片。  第三步:配置调试器 第四步:配置时钟 第五步: 配置时钟树,在下图所示出输入,点击回车即可。  第六步:配置串口  第七步: 第二部分: 代码编写 第一步:定义一个用于存放经度纬度的缓存

    2024年04月08日
    浏览(66)
  • STM32堆栈的大小及内存四(五)区的分析

    一般在编程时,我们都不需要考虑堆栈空间的大小,因为在启动文件中都对堆栈空间的大小进行了设置。 1.1.1、直接修改启动文件 如以下截取stm32启动文件部分汇编代码, Stack栈的大小为:0x400(1024Byte),Heap堆的大小为:0x200(512Byte)。 这也是为什么一个空的的工程编译后

    2024年02月05日
    浏览(42)
  • STM32OLED呈现主界面菜单任务的编程思路以及模板

    目录 一、效果展示(按键控制界面切换) 二、编程模板 1.头文件 2.库文件 三、编程思路 四、使用说明 OLED三级界面效果展示 1.先填充好每一个要显示的界面,确保界面显示没问题。 2.确保条件能触发,我这里选择的是4个按键控制。 3.先编写界面的横向切换,如下图所示。

    2024年02月16日
    浏览(37)
  • FreeRTOS的任务堆栈

    一、 FreeRTOS的任务堆栈 在FreeRTOS中,每个任务都有自己的堆栈。堆栈是用来存储任务运行时临时变量、函数返回地址等数据的一段内存空间。堆栈的大小是通过xTaskCreate()函数的参数指定的,通常情况下需要根据任务所需的局部变量的大小及递归调用深度来合理设置。 FreeRTO

    2024年02月14日
    浏览(39)
  • 基于STM32的实时操作系统FreeRTOS移植教程(手动移植)_stm32移植freertos(1)

    直接意识代码: 这是我们大脑最希望的添加代码方式,很显然他是 错的 , 两个任务之间产生了相互的影响 ,使得两个任务都执行错误,这种思想在 裸机开发 中肯定是 错的 ,但是在我们的 RTOS 中他就可以是 对的 。 任务型代码: 这是 独立的两个任务内容 ,我们只需要把

    2024年04月10日
    浏览(106)
  • 【FreeRTOS】FreeRTOS移植stm32详细步骤介绍

    我在查找FreeRTOS移植的相关教程特别少,所以想非常详细的介绍FreeRTOS移植stm32详细步骤,包括源码的下载,源码介绍,系统移植,代码验证等,每一步都有对应的介绍和解释,希望可以帮助到你们。 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分

    2024年02月08日
    浏览(45)
  • 【GD32/STM32】FreeRtos移植

    ​ (1)下载FreeRtos源码包 ​ FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions ​ (2)将源文件添加至工程 ​ (3)将GD32中的三个中断交由FreeRtos接管 ​ (4)配置管理FreeRTOS.h文件 ​ (5)FreeRtos基本使用方法 源码包结构 1.Demo中存放的

    2024年01月20日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包