STM32 堆栈的理解

发布者:JoyfulHearted最新更新时间: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  堆栈  内存分配 引用地址:STM32 堆栈的理解

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

推荐阅读最新更新时间:2024-11-10 13:28

STM32驱动OV7670摄像头寻迹(直线)初步调试成功
#include sys.h #include usart.h #include delay.h #include led.h #include usmart.h #include lcd.h #include ov7670.h #include exti.h #include timer.h //ALIENTEK Mini STM32开发板扩展实验9 extern u8 ov_sta; //在exit.c里面定义 extern u8 ov_frame; //在timer.c里面定义 //更新LCD显示 void camera_refresh(void) { u32
[单片机]
STM32】定时器TIM触发ADC采样,DMA搬运到内存
TIM+ADC+DMA原理 一般情况下,当我们需要进行采样的时候,需要用到ADC。例如:需要对某个信号进行定时采样(也就是隔一段时间,比如说2ms)。 本文提供的解决方案是:使用ADC的定时器触发ADC单次转换的功能,然后使用DMA进行数据的搬运! 这样只要设置好定时器的触发间隔,就能实现ADC定时采样转换的功能(即采样速率),然后可以在程序的死循环中一直检测DMA转换完成标志,然后进行数据的读取,或者使能DMA转换完成中断,这样每次转换完成就会产生中断。 主要需要解决的一个问题:定时器触发ADC采样,如何实现? 定时器触发ADC采样,是属于外部触发转换的一种方式。在《STM32中文参考手册》中,找到了关于这部分的
[单片机]
【<font color='red'>STM32</font>】定时器TIM触发ADC采样,DMA搬运到<font color='red'>内存</font>
STM32学习014_STC89C51RC
STC89C52rc是STC公司生产的一种低功耗、高性能的CMOS8位控制器,具有8k字节系统可编程FLASH存储器。stc89c51用的是经典的MCS-51内核,但是做了很多改进,使芯片具有传统51不具备的功能,但单芯上有灵活的8位CPU和系统可编程FLASH。 标准功能:8k字节Flash,512字节Ram,32位I/O口线,看门狗定时器,内置4KBEEPROM,max810复位电路,3个16位的定时器/计数器,4个外部中断,一个向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口,另外,stc89c52可降至0hz静态逻辑操作,支持两种软件可选择节电模式,空闲状态下,CPU停止工作,允许RAM,定时器/计数器,
[单片机]
STM32--简单的IAP操作
STM32支持在应用中编程,也就是所谓的IAP,这对产品的在线升级带来了很大方便。 在线升级的原理简介如下: 在单片机的FLASH中有两段代码,一段是IAP代码,另一段就是用户的应用程序即APP代码,IAP代码放在单片机复位时的起始地址,而APP代码则放在IAP后面的地址,上电时CPU首先执行IAP代码,再通过IAP代码跳转到APP代码开始执行。 在IAP代码执行期间,通过检测某一个事件(如IO电平)来判断是否对APP代码进行更新,如果该事件无效,则不更新,直接跳转到APP代码执行;如果该事件有效,则更新APP代码,而更新的文件则从外部磁盘通过串口或USB写入FALSH应用程序空间。 流程图如下: 当然,这只是一种最简单
[单片机]
STM32 F103 时钟树详解
刚入STM32 用了也有一段时间了,先做了中断,CAN,SPI。都是跟着网上的例子直接粘贴外设的初始化代码,看的大概能懂,但是时钟一直迷迷糊糊,不清不楚。 STM32为了实现低功耗,而设计的功能完善构成复杂的时钟系统,称之时钟树。使外设功能的时钟可自配置。因为STM32外设众多,而不同的项目用到的外设参差不齐,所以可控的时钟可以实现降低产品功耗。 所有的外设在使用之前都必须设置时钟信号,才可以正常工作。以STM32F103C8T6时钟树为例,如下图所示: 图7和图8道理一样的,大家觉得那个容易理解就看那个图 图8 STM32的四个时钟源 外部时钟 1 高速外部时钟(HSE):外部时钟源,晶振频率可取范围
[单片机]
<font color='red'>STM32</font> F103 时钟树详解
STM32调用SysTick_Config之后无法延时的奇怪问题
操作环境(蓝色粗体字为特别注意内容) 1,开发板:STM32F103C8T6最小系统核心板。 2,开发环境:Keil uv5 在我的工程里面用到SysTick_Config函数,如下: RCC_Configuration(); //系统时钟设置 NVIC_Configuration(); GPIO_Configuration(); //IO口初始化 Usart1_Init(); //串口1初始化 /* 配置systic作为1ms中断 */ if (SysTick_Config(72000)) //时钟节拍中断时1ms一次 用于定时 { /* Capture
[单片机]
嵌入式-stm32学习:位带操作
// GPIO 位操作 #include stm32f4xx.h // 这里只定义了GPIO ODR和IDR这两个寄存器的位带别名区地址,其他寄存器没有定义 //SRAM 位带区: 0X2000 0000~0X200F 0000 //SRAM 位带别名区: 0X2200 0000~0X23FF FFFF //外设位带区: 0X4000 0000~0X400F FFFF //外设位带别名区: 0X4200 0000~0X43FF FFFF // 把“位带地址+位序号”转换成别名地址的宏 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000
[单片机]
STM32与HC-SR04超声波测距
首先,先来看一下这个模块的基本功能和原理。 HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。像智能小车的测距以及转向,或是一些项目中,常常会用到。智能小车测距可以及时发现前方的障碍物,使智能小车可以及时转向,避开障碍物。 注意是5v输入,但是我用stm32 的3.3v输入也是没有问题的。 二.工作原理 1.给超声波模块接入电源和地。 2.给脉冲触发引脚(trig)输入一个长为20us的高电平方波 3.输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;(此时应该启动定时器计
[单片机]
<font color='red'>STM32</font>与HC-SR04超声波测距
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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