STM32 堆栈的理解

2019-12-02来源: eefocus关键字:STM32  堆栈  内存分配

1、MDK STM32的内存分配 (摘自网络)


C语言上分为栈、堆、bss、data、code段。具体每个段具体是存储什么数据的,直接百度吧。重点分析一下STM32以及在MDK里面段的划分。


MDK下Code,RO-data,RW-data,ZI-data这几个段:


Code是存储程序代码的。


RO-data是存储const常量和指令。


RW-data是存储初始化值不为0的全局变量。


ZI-data是存储未初始化的全局变量或初始化值为0的全局变量。


Flash=Code + RO Data + RW Data;


RAM= RW-data+ZI-data;


这个是MDK编译之后能够得到的每个段的大小,也就能得到占用相应的FLASH和RAM的大小,但是还有两个数据段也会占用RAM,但是是在程序运行的时候,才会占用,那就是堆和栈。在stm32的启动文件.s文件里面,就有堆栈的设置,其实这个堆栈的内存占用就是在上面RAM分配给RW-data+ZI-data之后的地址开始分配的。


堆:是编译器调用动态内存分配的内存区域。


栈:是程序运行的时候局部变量的地方,所以局部变量用数组太大了都有可能造成栈溢出。


2、M3手册相关内容


1、 工作模式

Cortex-M3 处理器支持两种工作模式,线程模式和处理模式:

1) 在复位时处理器进入线程模式, 异常返回时也会进入该模式。 特权和用户(非特权)


代码能够在线程模式下运行。


2) 出现异常时处理器进入处理模式,在处理模式中,所有代码都是特权访问的。


2、特权访问和用户访问

代码可以是特权执行或非特权执行。 非特权执行时对有些资源的访问受到限制或不允许

访问。特权执行可以访问所有资源。处理模式始终是特权访问,线程模式可以是特权或非特

权访问。

线程模式在复位之后为特权访问,但可通过 MSR 指令清零 CONTROL[0],将它配置为

用户(非特权)访问。用户访问禁止:

1) 部分指令的使用,例如设置 FAULTMASK 和 PRIMASK 的 CPS 指令。

2)对系统控制空间(SCS)的大部分寄存器的访问。


当线程模式从特权访问变为用户访问后,本身不能回到特权访问。只有处理操作能够改


变线程模式的访问特权。处理模式始终是特权访问的。


3、主堆栈和进程堆栈

结束复位后,所有代码都使用主堆栈。异常处理程序(例如 SVC)可以通过改变其在

退出时使用的 EXC_RETURN 值来改变线程模式使用的堆栈。所有异常继续使用主堆栈,堆

栈指针 r13 是分组寄存器,在 SP_main 和 SP_process 之间切换。在任何时候,进程堆栈和主

堆栈中只有一个是可见的,由 r13 指示。

除了使用从处理模式退出时的 EXC_RETURN 的值外,在线程模式中,使用 MSR 指令

对 CONTROL[1]执行写操作也可以从主堆栈切换到进程堆栈。


3、关于STM32的 主堆栈指针 和 进程堆栈指针 


1、RTOS调用sheduler之前,起作用的是MSP,PSP的值是00000

2、sheduler之后 , RTOS进入运行状态,在task的代码中时此时,起作用的是PSP栈指针 (图示为idel task)

3、进一步验证


在任务调度的代码中设置断点,任务调度过程一定不属于任何一个task。从断点看,任务调度过程使用的是MSP

继续debug,单步至调度过程结束,进入一个task代码,此时栈指针立刻切换到PSP。

4、结论


单片机启动时运行MSP栈,RTOS在执行调度时使用的是MSP


RTOS task运行时,使用的是当前task的栈,栈指针使用的是PSP


即粗略地可以认为 task代码段使用的都是PSP指针,而非task代码段使用任然是MSP指针


附:


1、查找系统栈的起始地址。


map文件中,关于栈的起始地址和大小都有描述。起始地址即栈的栈底地址,栈顶地址为栈低地址加上栈大小的地址


栈的设置如文件中描述,在arm_startup_nrf52.c中

2、在map中,查看heap的情况


startup文件中申请的heap内存管,如果没有被使用的话,会被编译器优化掉

如有错误,敬请斧正

关键字:STM32  堆栈  内存分配 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic481701.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32堆栈空间大小设置
下一篇:STM32-modbus rtu 之从机程序

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

简析stm32启动过程
说明:本文是杰杰以前保存下来的,出处已经不知道在哪了,应该是各大论坛中,当然转这种文章,到处都有。今天我就把它重写一遍。基于原作者的内容添加一些内容(源码)讲解。杰杰水平有限,出错在所难免,还望各位大神指点一二。startup_stm32f10x_cl.s互联型的STM32F105xx,STM32F107xxstartup_stm32f10x_hd.s 大容量的STM32F101xx,STM32F102xx,STM32F103xxstartup_stm32f10x_hd_vl.s 大容量的STM32F100xxstartup_stm32f10x_ld.s 小容量的STM32F101xx,STM32
发表于 2019-12-14
简析stm32启动过程
【干货】老外的GitHub整理的stm32f4驱动库
昨晚在github发现了一个老外自己整理的封装库,有很多,比如一些通讯啊啥的,一些显示屏驱动等等目录STM32F4Libraries and projectsHere are listed all libraries for STM32F4 devices.Libraries are designed to work with STM32F4xx series of MCU. Every project hereis created with Keil uVision, but tested with GCC compiler too (Coocox). Eachproject includes 4 targets
发表于 2019-12-14
【干货】老外的GitHub整理的stm32f4驱动库
基于Linux的kfifo移植到STM32(支持os的互斥访问)
关于kfifokfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现;它提供一个无边界的字节流服务,最重要的一点是,它使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场情时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。具体什么是环形缓冲区,请看我以前的文章说明关于kfifo的相关概念我不会介绍,有兴趣可以看他的相关文档,我只将其实现过程移植重写,移植到适用stm32开发板上,并且按照我个人习惯重新命名,RingBuff->意为环形缓冲区RingBuff_t环形缓冲区的结构体成员变量,具体含义看注释。buffer: 用于存放
发表于 2019-12-14
STM32之重定向printf
学习stm32,打交道最多的莫过于串口通讯了,但是官方的串口发送库太恶心了,完全不好用甚是还念C语言的printf,想输出什么就有什么,现在,一步步来做个重定向,让你的stm32可以跟C语言一样能想看什么就看什么:首先:添加printf的头文件 :#include <stdio.h>    //当时学C语言最熟悉的stdio.h其次:改写int fputc(int ch, FILE *f)函数int fputc(int ch, FILE *f);int fputc(int ch, FILE *f){USART_SendData(USARTx, (uint8_t) ch);while
发表于 2019-12-14
STM8L051F3_02_EXTI应用
本章介绍STM8L051F3的EXTI相关知识,内容分为以下几部分:EXTI简介KEY外部中断检测1、EXTI简介EXTI也是属于GPIO的知识点,应用比较广泛。STM8L051F3每个I/O口在输入模式下都能配置为中断,在这个配置下,一个信号沿或电平输入到I/O口上将产生一个中断请求。外部中断只有在端口的输入模式下才有效。可通过配置寄存器Px_CR2相应的位来独立地使能或禁能某个端口的外部中断功能。另外,可通过ADC_TDRH和ADC_TDRL寄存器来禁用施密特触发器节省功耗。2、KEY外部中断检测2.1 KEY的外部中断配置本小节介绍将GPIO配置为外部中断输入模式,并通过KEY(PC4)来触发一个外部中断信号,然后产生中
发表于 2019-12-14
STM8L051之通过ADC1与DMA读取内部参考电压
stm8L051芯片内部的参考电压与电源电压有一定的关系这在芯片供电电压变化的情况下,测量外部ADC电压输入提供一个确定的参考电压。这里提前厘清下:该内部参考电压VREFINT 并非ADC 的参考电压,ADC 的参考电压依然是VDD。即使VDD 有所波动,这个VREFINT 电压恒定不变,对于ADC 电路而言,它只是个测试点。 对于某固定的ADC 参考电压情况下,所有被测电压点的AD转换值与该点电压值保持同一比例关系,换句话说,对于ADC参考电压固定情况下,各点的电压与ADC值与成线性关系。下面图形是芯片分别在3个不同参考电压的示意图,这里参考电压接VDD。下面三根斜线分别是VDD 为2.8V、3.2V、3.6V 时的
发表于 2019-12-14
STM8L051之通过ADC1与DMA读取内部参考电压
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved