详细解析STM32中的堆栈机制
STM32内存分配解析及变量的存储位置
STM32内存分配解析及变量的存储位置原⽂内存映射在⼀些桌⾯程序中,整个内存映射是通过虚拟内存来进⾏管理的,使⽤⼀种称为内存管理单元(MMU)的硬件结构来将程序的内存映射到物理RAM。
在对于 RAM 紧缺的嵌⼊式系统中,是缺少 MMU 内存管理单元的。
因此在⼀些嵌⼊式系统中,⽐如常⽤的 STM32 来讲,内存映射被划分为闪存段(也被称为Flash,⽤于存储代码和只读数据)和RAM段,⽤于存储读写数据。
STM32 的 Flash 和 RAM 地址范围笔者标题所说的内存是指 STM32 的 Flash 和 RAM,下图是 ARM Cortex M3 的地址映射图:从图中我们可以看到 RAM 地址是从 0x2000 0000 开始的,Flash地址是从 0x0800 0000 开始的,笔者将在下⽂中着重对这两部分进⾏剖析。
Flash代码和数据是存放在 flash 中的,下⾯是将 flash 内部进⾏细分之后的⼀张图,图中标明了代码段,数据段以及常量在 flash 中的位置。
如上图所⽰,Flash ⼜可以细分为这么⼏个部分,分别是⽂本段 (Text),其中⽂本段中⼜包含可执⾏代码 (Executable Code)和常量 (Literal Value),在⽂本段之后就是只读数据区域 (Read Only Data),当然并不是所有架构的单⽚机都满⾜这样⼀个排布规律,这⾥只针对ARM Cortex M3 系列,只读数据段后⾯接着的就是数据复制段 (Copy of Data Section),第⼀次遇到这个概念的朋友看到数据复制可能会有所疑惑,其实这个段充当的作⽤是存放程序中初始化为⾮ 0 值的全局变量的初始值,之所以要将初始值存放到这⾥,是因为全局变量是存放在 RAM 上的,RAM 上的值掉电便丢失,每次上电后这些变量是要进⾏重新赋值的,⽽重新赋的值就存放在这⾥。
那为什么不存放初始化为 0 的全局变量初始值呢,原因也很简单,既然是初始化为 0,那么在上电后统⼀对存放初始化为 0 的全局变量的那块区域清0就好了。
深入理解STM32双堆栈机制
深入理解STM32双堆栈机制堆栈堆栈,「堆」和「栈」经过无数技术书籍,以及各类技术博主苦口婆心的提醒,恐怕没几个人会再把堆和栈混为一谈,精明的开发者都明白,堆栈堆栈,「堆」和「栈」是不同的两种数据结构,具有各自的内存分配和使用方式。
众所周知,栈由编译器自动分配释放,堆由程序员手动分配释放,栈存放函数形参、局部变量,堆内存申请了记得释放……诸如此类,老生常谈。
众所不周知,在不同的体系结构、裸机/操作系统下,堆栈在内存中的分配方式、内存布局、空间大小、存储内容也存在差异。
本文以 STM32 系列芯片(Cortex-M3 内核)和 RT-Thread 操作系统为例,梳理嵌入式开发过程中,与 MCU 堆栈有关的概念,然而堆栈涉及的知识太多,本文只侧重从内存分布角度阐述,帮助读者整体把握相关技术。
程序为什么需要堆栈堆栈是程序访问内存的一种方式。
程序员在编程处理应用数据时,往往要使用大块连续的内存空间。
程序指令在执行运算的过程中,也有大量中间结果需要临时保存,显然这些数据都是存放在内存当中,堆和栈便提供了这样一种机制:将内存分类管理,提供不同的访问方式。
堆和栈的使用更具体表现为,编程中使用的malloc()函数从堆内存分配空间,利用指针数组或内存函数使用。
程序编译后所包含的大量PUSH和POP指令操作,系统根据SP(堆栈指针)寄存器访问当前对应栈内存,通过栈保存临时数据。
堆和栈在内存中的具体位置,是接下面篇幅中讨论的重点。
当然,内存空间只是连续字节数据的抽象,本身并不区分堆和栈的概念,它做的只是存储和读写信息。
因此,如何定义堆栈、初始化建立堆栈环境,在嵌入式软件运行前便显得尤为重要。
这涉及到处理器提供的堆栈机制、操作系统内存管理和进程切换等方方面面。
程序内存布局在芯片内部存储器中,包含了代码、数据、堆栈等信息,存放在 Flash 和 SRAM 当中,这里有必要说明一下众多内存类型的地址空间分布,其中包含我们的主角 —— 堆栈。
【STM32F429】第5章ThreadXNetXDUO网络协议栈介绍
【STM32F429】第5章ThreadXNetXDUO⽹络协议栈介绍第5章 ThreadX NetXDUO⽹络协议栈介绍本章节介绍 ThreadX NetXDUO⽹络协议栈,让⼤家对NetXDUO有⼀个整体的了解。
5.1 初学者重要提⽰5.2 Express Logic公司介绍5.3 ThreadX NetXDUO简介5.4 ThreadX NetXDUO安全认证5.5 ThreadX NetXDUO⽀持的RFC5.6 ThreadX NetXDUO的IxANVL测试5.7 ThreadX NetXDUO的IPv6就绪微标认证5.8 ThreadX NetXDUO各⾏各业应⽤案例5.9 总结5.1 初学者重要提⽰ThreadX是⼩型RTOS的巅峰之作,通过了各⾏各业的安全认证,并且⼤部分都是最⾼安全标准。
作为中间件的NetXDUO协议栈也通过了各种安全认证。
5.2 Express Logic公司介绍ThreadX的作者是William lamie(同样是Nucleus RTOS的原始作者,于1990年发布)。
1996的时候成⽴了Express Logic,并于1997发布⾸版ThreadX RTOS。
ThreadX4发布于2001年,ThreadX5发布于2005年,ThreadX6发布于2020年。
FileX – ThreadX的嵌⼊式⽂件系统于1999年发布⾸版。
NetX – ThreadX的嵌⼊式TCP / IP⽹络协议栈于2002年发布⾸版。
USBX – ThreadX的嵌⼊式USB协议栈于2004年发布⾸版。
2009年推出了适⽤于SMP多核环境的ThreadX。
2011年发布⽀持动态应⽤加载的ThreadX Modules。
GUIX – ThreadX的嵌⼊式UI于2014年发布⾸版。
Microsoft在2019年4⽉18⽇以未公开的价格购买了Express Logic。
5.2.1 ThreadX内核ThreadX⼏乎是⼩型RTOS的巅峰之作,不管你之前⽤的那个OS,如果有精⼒建议还是学习下。
一文解析STM32内存管理和堆栈的认知与理解
一文解析STM32内存管理和堆栈的认知与理解本文主要介绍了STM32内存管理和堆栈的认知与理解,首先介绍的是内存管理的实现原理及分配、释放原理,其次介绍了stm32的存储器结构,最后阐述了堆栈的认知与理解,具体的跟随小编一起来了解一下吧。
STM32内存管理详解内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。
其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。
内存管理的实现方法有很多种,他们其实最终都是要实现2 个函数:malloc 和free;malloc 函数用于内存申请,free 函数用于内存释放。
内存管理的实现原理从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。
内存池被等分为n 块,对应的内存管理表,大小也为n,内存管理表的每一个项对应内存池的一块内存。
内存管理表的项值代表的意义为:当该项值为0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。
比如某项值为10,那么说明包括本项对应的内存块在内,总共分配了10 个内存块给外部的某个指针。
内寸分配方向如图所示到低位地址)即首先从最末端开始找空内存。
当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。
分配原理当指针p 调用malloc 申请内存的时候,先判断p 要分配的内存块数(m),然后从第n 项开始,向下查找,直到找到m 块连续的空内存块(即对应内存管理表项为0),然后将这m 个内存管理表项的值都设置为m(标记被占用),最后,把最后的这个空内存块的地址返回指针p,完成一次分配。
注意,如果当内存不够的时候(找到最后也没找到连续的m 块空闲内存),则返回NULL 给p,表示分配失败。
释放原理。
学习STM32(二)之STM32内存管理(三)STM32内存管理以及堆和栈的理解
学习STM32(⼆)之STM32内存管理(三)STM32内存管理以及堆和栈的理解⾸先,先看⼀下stm32的存储器结构。
以下两种说法都⼀样的,各有着重⽽已,可单看第⼀个说法,第⼆个知道就⾏第⼀个说法:原⽂ :STM32的存储器映射详解存储器映射是指把芯⽚中或芯⽚外的FLASH,,外设,BOOT,BLOCK等进⾏统⼀编址。
即⽤地址来表⽰对象。
这个地址绝⼤多数是由⼚家规定好的,⽤户只能⽤⽽不能改。
⽤户只能在挂外部RAM或FLASH的情况下可进⾏⾃定义。
Corx-M3⽀持4GB的存储空间,它的存储系统采⽤统⼀编址的⽅式; 程序存储器、数据存储器、被组织在4GB的线性地址空间内,以⼩端格式(little-endian)存放。
由于Cortex-M3是32位的内核,因此其PC指针可以指向2^32=4G的地址空间,也就是0x0000_0000——0xFFFF_FFFF这⼀⼤块空间。
见图1:图1:Cortex-M3的存储器映射Cortex-M3内核将0x0000_0000——0xFFFF_FFFF这块4G⼤⼩的空间分成8⼤块:代码、SRAM、外设、外部RAM、外部设备、专⽤外设总线-内部、专⽤外设总线-外部、特定⼚商(见图1)。
这就导致了,使⽤该内核的芯⽚⼚家必须按照这个进⾏各⾃芯⽚的存储器结构设计,如。
图2:Cortex-M3与中密度stm32的存储器映射对⽐图三:图2中可以很清晰的看到,STM32的存储器结构和Cortex-M3的很相似(这是因为stm32本来就是按照cortex_m3内核来设计硬件的),不同的是,STM32加⼊了很多实际的东西,如:Flash、SRAM等。
只有加⼊了这些东西,才能成为⼀个拥有实际意义的、可以⼯作的处理芯⽚——STM32。
STM32的存储器地址空间被划分为⼤⼩相等的8块区域,每块区域⼤⼩为512MB(如:0x20000000~0x40000000)。
对STM32存储器知识的掌握,实际上就是对Flash和SRAM这两个区域知识的掌握。
STM32堆栈整理
STM32内存编程在startup_stm32f10x_md.s文件中,它的前面几行就有以上定义,;栈=1KStack_Size EQU 0x00000400;堆=512BHeap_Size EQU 0x00000200Stack_Size不影响Hex,更不影响Hex怎么运行的,只是在Debug调试时会提示错。
栈溢出也有是超过了国界进行活动,只要老外没有意见,你可以接着玩,有老外不让你玩,你就的得死,或是大家都死(互相撕杀),有的人写单片机代码在函数里定义一个大数组int buf[8192],栈要是小于8192是会死的很惨。
Heap_Size可为0,即不使用动态分配。
Heap_Size的大小与malloc所分配的内存有关,当连续分配而又不释放,会导致满堆或内存泄露。
本文源起的诉求,即在object过多的情况下进行解析,程序需要N多次的动态内存分配,而Heap_Size太小,导致无法分配内存。
通过修改Heap_Size的大小解决了诉求。
STM32的内存分配规律从0X20000000开始依次为:静态存储区+堆区(可有可无)+栈区所有的全局变量,包括静态变量之类的,全部存储在静态存储区。
紧跟静态存储区之后的,是堆区(如没用到malloc,则没有该区),之后是栈区。
附录STM32内存地址说明在MDK编译过程中,内存的划分如下:Code是存储程序代码的。
RO-data是存储const常量和指令。
RW-data是存储初始化值不为0的全局变量。
ZI-data是存储未初始化的全局变量或初始化值为0的全局变量。
Flash=Code + RO Data + RW Data;RAM= RW-data+ZI-data;此内存划分暂未包括堆栈,堆栈会在程序运行时,占用RAM。
堆栈的内存占用就是MDK里,RAM分配给RW-data+ZI-data之后的地址开始分配的。
---------------------STM32的堆栈大小在官方文件已经定义好了,分别是:Heap_Size EQU 0x00000200 一共512字节Stack_Size EQU 0x00000400 一共1K字节/***********************************************************************************/但是STM32在keil环境下每次编译后的堆栈起始地址并不是固定的(就算事先已经定义好了堆栈的大小),因为栈的起始地址是由用户程序中事先定义好的变量数目决定的(实测是如此)。
stm32 单机程序栈保护机制
stm32 单机程序栈保护机制
STM32单片机的程序栈保护机制是一种用于保护程序运行时堆栈空间的技术。
在STM32单片机中,堆栈保护可以通过使用硬件和软件相结合的方式来实现。
下面我将从硬件和软件两个方面来介绍STM32单片机的程序栈保护机制。
硬件方面:
STM32单片机的硬件提供了一些特性来保护程序的堆栈空间。
其中最常见的是硬件堆栈保护功能。
在STM32单片机中,可以通过设置相关的寄存器来启用硬件堆栈保护。
这样可以防止堆栈溢出和堆栈破坏,提高系统的稳定性和安全性。
另外,STM32单片机还提供了一些特殊的寄存器和机制,用于监控堆栈的使用情况,比如堆栈指针寄存器(SP)和堆栈溢出检测机制等。
这些硬件特性可以帮助开发人员及时发现和处理堆栈相关的问题,保障程序的正常运行。
软件方面:
除了硬件保护机制,STM32单片机的程序堆栈还可以通过软件
来进行保护。
比如,开发人员可以在编写程序时,合理规划堆栈的
大小,避免出现堆栈溢出的情况。
此外,还可以通过编写堆栈溢出
检测的代码来监控堆栈的使用情况,及时发现并处理堆栈溢出的问题。
另外,开发人员还可以通过使用一些静态分析工具或者动态调
试工具来检测程序中可能存在的堆栈问题,及时进行修复和优化。
总结:
综上所述,STM32单片机的程序堆栈保护机制包括硬件和软件
两个方面。
通过合理配置硬件保护特性和编写规范的软件代码,可
以有效保护程序的堆栈空间,提高系统的稳定性和安全性。
开发人
员在使用STM32单片机时,应该充分了解和掌握这些堆栈保护技术,以确保程序的正常运行。
计算机组成原理中的堆栈简介
计算机组成原理中的堆栈简介
计算机组成原理中的堆栈是一种数据结构,它遵循后进先出(LIFO)的原则。
堆栈通常用于存储函数调用、临时变量和其他临
时数据。
在计算机组成原理中,堆栈通常是通过内存中的一段特定
区域来实现的。
堆栈通常由两个主要操作组成,压栈(push)和弹栈(pop)。
压栈操作将数据放入堆栈顶部,而弹栈操作则从堆栈顶部移除数据。
这种操作使得最后压入堆栈的数据最先被弹出,因此堆栈遵循LIFO
原则。
在计算机组成原理中,堆栈经常用于存储函数调用的返回地址
和局部变量。
当一个函数被调用时,当前函数的返回地址会被压入
堆栈,以便在函数执行完毕后能够返回到正确的位置。
同时,函数
内部的局部变量也可以被存储在堆栈中,以便在函数执行期间可以
方便地访问和操作这些变量。
堆栈还可以用于表达式求值和语法分析。
例如,后缀表达式的
求值就可以通过堆栈来实现。
在语法分析中,堆栈可以用于存储和
处理语法规则,以便进行语法分析和语法树的构建。
在计算机硬件中,堆栈通常与栈指针(stack pointer)和基址
寄存器(base pointer)相关联。
栈指针指向当前堆栈顶部的位置,而基址寄存器则指向堆栈的基址,用于定位局部变量和函数参数的
存储位置。
总的来说,堆栈在计算机组成原理中扮演着重要的角色,它不
仅是一种数据结构,还在函数调用、表达式求值和语法分析等方面
发挥着重要作用。
深入理解堆栈的原理和应用对于理解计算机组成
原理和编程语言的工作原理至关重要。
堆栈的名词解释
堆栈的名词解释堆栈是计算机领域中一个重要的概念,它是一种数据结构,用于存储和管理数据。
堆栈的特点主要体现在数据存储和访问的方式上,它采用“后进先出”(Last-In-First-Out,简称LIFO)的策略,即最后进入堆栈的数据首先被访问。
1. 堆栈的基本原理堆栈由两个主要操作组成:压入(Push)和弹出(Pop)。
当数据需要被添加到堆栈中时,使用压入操作将数据放置在堆栈的顶部;而当数据需要被访问或移除时,使用弹出操作将顶部的数据取出。
这种方式确保了最后添加的数据能够最先被处理,类似于将数据放置在空心的立方体中,只能从顶部进行操作。
2. 堆栈的实际应用堆栈在计算机领域有着广泛的应用,尤其在编程和算法设计中扮演着重要的角色。
堆栈可以用来解决很多实际问题,比如表达式求值、函数调用、内存管理等。
2.1 表达式求值在数学表达式的求值过程中,堆栈可以帮助解决算术优先级问题。
将表达式的各个操作数和运算符通过压入操作按正确的顺序入栈,然后使用弹出操作依次取出并计算,最终得到求值结果。
2.2 函数调用在程序开发中,函数调用是非常常见的操作。
当一个函数被调用时,所有的局部变量和函数参数将被压入堆栈中,函数执行完毕后再依次通过弹出操作移除。
这种方式保证了函数之间的数据独立性和内存分配的有序性。
2.3 内存管理堆栈也可以用于内存管理。
当程序需要为局部变量分配内存空间时,会通过压栈操作将其保存在堆栈中。
当变量不再需要时,可以通过弹出操作从堆栈中释放内存,从而实现对内存的高效管理。
3. 堆栈的实现方式在计算机中,堆栈可以通过不同的数据结构来实现,比较常见的有数组和链表。
3.1 数组实现使用数组实现堆栈是一种简单且高效的方式。
数组具有随机访问的特性,只需通过指针指向栈顶元素即可。
压入操作只需将元素放置在栈顶指针的下一个位置,而弹出操作则是将栈顶元素移除。
3.2 链表实现链表实现堆栈也是一种常见的方式。
链表中的每个节点都包含一个数据元素和一个指向下一个节点的指针。
一个故事看懂单片机中的堆栈(完整版)
一个故事看懂单片机中的堆栈(完整版)因为单片机有CPU、存储器、IO等等,使他(人性化一点以配合下文)看起来就像一个比较小的计算机,所以,在理解单片机的时候如果能把你之前有的那些也许仅仅是直觉上的对计算机的理解融入进来的话,可能会对你学习单片机的概念有极大的帮助,至少对于我是这样的。
我想在关于单片机的众多让你头晕脑胀、摸不着头脑甚至想撞墙的概念里面,“堆栈”可能是其中最可恶的一个,因为即使单单是从汉语的角度来理解这个词就已经让你很晕了,其实我最初也想不通这是哪位大侠的创意,不过不用担心,这里我们完全不去讨论关于这个词的问题(这个词用得其实很好“堆”和“栈”都有他们各自的意思,准确的概括了这个区域的功能,有兴趣可以Baidu一下),这里我会打一个比较有趣的比方,以此来绕过那些令你想撞墙的概念,并使你在直觉上对“堆栈”这个概念有一个深刻的理解。
你基本上应该清楚,单片机里面是有存储区和CPU的,如果你不清楚,那么我刚刚告诉你了,请记住。
现在,请你把单片中的CPU想成一个人(你完全可以把他想成是你宿舍的那个天天和你吵嘴的同学,一会你就会发现这会非常有趣),在这里就叫他C哥吧,不过这个人不同于常人,有一些特点,一会我们会慢慢说清楚,现在要告诉你的关于这个人的第一个特点是:他的记忆能力很差。
下面,请你把存储区想象成一个一个排好的小盒子,这些盒子的作用大致可以分成两类:1、保存写有你命令的纸条,比如你在某个盒子里面的纸条上写着:去洗我的袜子!;2、保存你的一些东西,比如你那双正在污染宿舍空气的臭袜子。
因为C哥是一个记忆力不怎么好的人,所以,这些盒子都有自己的编号,以方便他查找。
那么,现在,我们可以来说明一下单片机是如何工作的了。
首先,你要把所有的命令还有需要处理的东西放进那些小盒子,比如刚才提到的你那双待洗的袜子还有那张纸条,这时你应该发现C哥另一个特点:笨——他只会做你明确告诉他的事情,也就是说,如果你没有在纸条上写“去洗我的袜子!”,那么C哥极有可能会无动于衷地看着你的袜子直到他被熏晕倒,当然,更可能的情况是他根本找不到你的袜子…好了,当你把要做的事情和该怎么做写到盒子里之后,下面的任务就交给C哥了。
STM32内存管理以及STM32中的堆栈
STM32内存管理以及STM32中的堆栈
今天仔细读了一下内存管理的代码,然后还有看了堆栈的相关知识,把以前不太明白的一些东西想通了。
首先,先看一下stm32的存储器结构。
Flash,SRAM寄存器和输入输出端口被组织在同一个4GB的线性地址空间内。
可访问的存储器空间被分成8个主要块,每个块为512MB。
FLASH存储下载的程序。
SRAM是存储运行程序中的数据。
所以,只要你不外扩存储器,写完的程序中的所有东西也就会出现在这两个存储器中。
这是一个前提!
堆栈的认知
1. STM32中的堆栈。
这个我产生过混淆,导致了很多逻辑上的混乱。
首先要说明的是单片机是一种集成电路芯片,集成CPU、RAM、ROM、多种I/O口和中断系统、定时器/计数器等功能。
CPU中包括了各种总线电路,计算电路,逻辑电路,还有各种寄存器。
Stm32有通用寄存器R0‐R15 以及一些特殊功能寄存器,其中包括了堆栈指针寄存器。
当stm32正常运行程序的时候,来了一个中断,CPU就需要将寄存器中的值压栈到RAM里,然后将数据所在的地址存放在堆栈寄存器中。
等中断处理完成退出时,再将数据出栈到之前的寄存器中,这个在C语言里是自动完成的。
2. 编程中的堆栈。
在编程中很多时候会提到堆栈这个东西,准确的说这个就是RAM中的一个区域。
我们先来了解几个说明:
(1) 程序中的所有内容最终只会出现在flash,ram里(不外扩)。
(2) 段的划分,是将类似数据种类存储在一个区域里,方便管理,但正如上面所说,不管。
堆栈计算机的原理和实现
堆栈计算机的原理和实现首先,堆栈是一种后进先出(LIFO)的数据结构,它类似于一个箱子,可以将数据存放在顶部并从顶部取出数据。
堆栈指令集是一组用于操作堆栈的指令,它包括入栈、出栈、交换栈顶元素和复制栈顶元素等操作。
堆栈指令集可以通过硬件实现,也可以通过软件仿真实现。
堆栈计算机的工作原理是将指令和数据存储在一个堆栈中,并通过一组堆栈指令来对堆栈进行操作。
在堆栈计算机中,所有的计算都是通过堆栈指令来完成的。
当执行一个指令时,计算机从堆栈中取出指令并执行相应的操作。
例如,如果执行一个加法指令,计算机将从堆栈中弹出两个操作数,并将它们相加后将结果压入堆栈。
堆栈计算机的实现过程包括设计堆栈的数据结构、实现堆栈指令集、设计堆栈指令解码器和实现堆栈指令执行器等。
首先,需要设计一个能够存储指令和数据的堆栈数据结构。
堆栈数据结构可以使用寄存器堆栈、内存堆栈或者是一组寄存器来实现。
接下来,需要设计并实现一组堆栈指令,这些指令可以实现堆栈的操作,如入栈、出栈、交换栈顶元素和复制栈顶元素等。
然后,需要设计并实现一个堆栈指令解码器,用于将指令解码为具体的操作。
最后,需要实现一个堆栈指令执行器,它可以执行解码后的指令并更新堆栈中的数据。
与传统的基于寄存器的计算机体系结构相比,堆栈计算机具有一些优势。
首先,堆栈指令的长度相对较短,可以节省存储空间。
其次,堆栈计算机可以轻松支持函数调用、递归和表达式求值等高级语言的特性。
此外,由于堆栈计算机的指令集通常较小,因此它的硬件实现往往更加简单和廉价。
然而,堆栈计算机也存在一些限制和缺点。
由于堆栈指令执行速度较慢,相同的计算可能会在堆栈计算机上花费更长的时间。
此外,由于堆栈计算机不支持直接访问内存,它可能不适合处理需要频繁访问内存的应用程序。
综上所述,堆栈计算机是一种基于堆栈数据结构的特殊计算机体系结构。
它通过堆栈指令集和堆栈的操作来实现指令的执行和数据的处理。
堆栈计算机的实现需要设计堆栈数据结构、堆栈指令集、堆栈指令解码器和堆栈指令执行器等组件。
嵌入式单片机stm32原理及应用课后答案
嵌入式单片机stm32原理及应用课后答案一、判断题(在题后的括号内打√或×):1. 单片机根据数据总线宽度的不同,可以分为4位机、8位机、16位机、32位机。
(√ )2. MCS-51系列单片机分成三大字系列:51子系列、52子系列和53子系列。
(× )3. 一般在计算机中,对于正数,最高位规定为“0”;对于负数,最高位规定为“1”。
(√ )4. MCS-51的特定功能寄存器原产在60H~80H地址范围内。
(× )5. P2口既可以作为I/O使用,又可以作地址/数据复用口使用。
(√ )6. 按指令继续执行时间分后,可以分成1周期、2周期、3周期指令。
(× )7. 定时/计数器共有5种工作方式,由TMOD中M1M0的状态决定。
(× )8. 异步通信的数据或字符就是分成一帧一帧地传输,用一个初始位则表示字符的已经开始,用暂停位则表示字符的完结。
(√)9. MOV 20H , R1 (√ )10. SUB A,R2 (× )二、单选题(请选择正确答案填写在括号中)1. 所谓CPU就是指( A )。
(A)运算器和控制器(C)输入输出设备 (B)运算器和存储器 (D)控制器和存储器2. .101B转换成十进制数是( D )。
(A)46.625 (B)23.625 (C) 23.62 (D) 21.6253. 能够用紫外光擦除ROM中程序的只读存储器称为( C )。
(A)掩膜ROM (B)PROM (C)EPROM (D)EEPROM4. 若某存储器芯片地址线为12根,那么它的存储容量为( B )。
(A)1KB (B) 2KB (C)4KB (D)8KB5. PC中存放的是( A )。
(A)下一条指令的地址 (B)当前正在继续执行的指令(C)当前正在执行指令的地址 (D)下一条要执行的指令6. 单片机的( D )口的插槽,还具备外中断、以太网通信等第二功能。
一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc
一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc大家好,我是无际。
有一周没水文了,俗话说夜路走多了难免遇到鬼。
最近就被一个热心网友喷了。
说我的文章没啥营养,所以今天来一篇烧脑的。
哈哈,开个玩笑,不要脸就没人能把我绑架。
主要是最近研发第二代物联网网关项目,必须要用到一个功能:内存管理。
温馨提醒,全文4700多字,其中技术点是你进阶到高手必须要学习的,最好收藏,反复专注地看,否则可能会感觉在看天书。
说到内存管理大家会可能想到malloc和free函数。
在讲这两个函数之前,我们先来讲讲栈(stack)和堆(heap)的概念。
1.栈(stack)我们单片机一般有个启动文件,拿STM32F103来举例。
这个Stack_Size就是栈大小,0x00000400就是代表有1K (0x400/1024)的大小。
那这个栈到底用来干嘛的呢?比如说我们函数的形参、以及函数里定义的局部变量就是存储在栈里,所以我们在函数的局部变量、数组这些不能超过1K(含嵌套的函数),否则程序就会崩溃进入hardfaul。
除了这些局部变量以外,还有一些实时操作系统的现场保护、返回地址都是存储在栈里面。
还有一点题外话,就是栈的增长方向是从高地址到低地址的,这个用得不多,暂时不需要去深究。
2. 堆(heap)malloc()函数动态分配的内存就属于堆的空间。
同样,在单片机启动文件里也有对堆大小的定义。
0x00000200就是代表有512个字节。
这意味着如果你用malloc()函数,那么最大分配的内存不能大于512字节,否则程序会崩溃。
网上很多文章说,全局变量和静态变量是放在堆区。
但是我做了实验,把堆的空间大小设置成0,程序正常运行并无影响。
这说明我们平时定义的全局变量、静态变量是不存放在堆的,而是堆栈以外的另外一篇静态空间区域,个人理解,如果有误请指正。
Ok,那么我们简单了解了堆和栈的概念,也知道malloc()函数分配的是堆的空间。
STM32堆栈大小详解以及变量存储位置
STM32堆栈大小详解以及变量存储位置栈增长和大端/小端问题是和CPU相关的两个问题.1,首先来看:栈(STACK)的问题.函数的局部变量,都是存放在'栈'里面,栈的英文是:STACK.STACK的大小,我们可以在stm32的启动文件里面设置,以战舰stm32开发板为例,在startup_stm32f10x_hd.s里面,开头就有:Stack_Size EQU 0x00000800表示栈大小是0X800,也就是2048字节.这样,CPU处理任务的时候,函数局部变量做多可占用的大小就是:2048字节,注意:是所有在处理的函数,包括函数嵌套,递归,等等,都是从这个'栈'里面,来分配的.所以,如果一个函数的局部变量过多,比如在函数里面定义一个u8 buf[512],这一下就占了1/4的栈大小了,再在其他函数里面来搞两下,程序崩溃是很容易的事情,这时候,一般你会进入到hardfault....这是初学者非常容易犯的一个错误.切记不要在函数里面放N多局部变量,尤其有大数组的时候!对于栈区,一般栈顶,也就是MSP,在程序刚运行的时候,指向程序所占用内存的最高地址.比如附件里面的这个程序序,内存占用如下图:图中,我们可以看到,程序总共占用内存:20 2348字节=2368=0X940那么程序刚开始运行的时候:MSP=0X2000 0000 0X940=0X2000 0940.事实上,也是如此,如图:图中,MSP就是:0X2000 0940.程序运行后,MSP就是从这个地址开始,往下给函数的局部变量分配地址.再说说栈的增长方向,我们可以用如下代码测试://保存栈增长方向//0,向下增长;1,向上增长.static u8 stack_dir;//查找栈增长方向,结果保存在stack_dir里面.void find_stack_direction(void){static u8 *addr=NULL; //用于存放第一个dummy的地址。
stm32堆栈,rom,flash详细理解
stm32堆栈,rom,flash详细理解精⼼总结⾸先⼀个程序被加载到内存中,这块内存⾸先就存在两种属性:静态分配内存和动态分配内存。
静态分配内存:是在程序编译和链接时就确定好的内存。
动态分配内存:是在程序加载、调⼊、执⾏的时候分配/回收的内存。
任何⼀个程序本质上都是由 bss段、data段、text段三个组成的。
C语⾔上分为栈、堆、bss、data、code段。
bss段: bss段(bss segment)通常是指⽤来存放程序中未初始化的全局变量的⼀块内存区域。
bss是英⽂Block Started by Symbol的简称。
bss段属于静态内存分配。
data段: 数据段(data segment)通常是指⽤来存放程序中已初始化的全局变量的⼀块内存区域。
数据段属于静态内存分配。
text段: 代码段(code segment/text segment)通常是指⽤来存放程序执⾏代码的⼀块内存区域。
这部分区域的⼤⼩在程序运⾏前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
在代码段中,也有可能包含⼀些只读的常数变量,例如字符串常量等。
注意:l BSS区(未初始化数据段):并不给该段的数据分配空间,仅仅是记录了数据所需空间的⼤⼩。
l DATA(初始化的数据段):为数据分配空间,数据保存在⽬标⽂件中。
上⾯这三段内存就组成了我们编写的程序的本体,但是⼀个程序运⾏起来,还需要更多的数据和数据间的交互,否则这个程序就是死的,⽆⽤的。
所以我们还需要为更多的数据和数据交互提供⼀块内存——堆栈。
堆(heap): 堆是⽤于存放进程运⾏中被动态分配的内存段,它的⼤⼩并不固定,可动态扩张或缩减。
当进程调⽤malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张); 当利⽤free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
栈(stack): 栈⼜称堆栈,是⽤户存放程序临时创建的局部变量, 也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。
堆栈知识详解(简单易懂)ppt课件
最新编辑ppt
15
Push函数
template<class T> Stack<T>& Stack<T>::Push(const T& x) {// Push x to stack.
if (IsFull()) throw NoMem(); // Push fails stack[++top] = x; return *this; }
信息技术科学学院
最新编辑ppt
29
Pop
template<class T> LinkedStack<T>& LinkedStack<T>::Pop(T& x) {// Delete top element and put it in x.
if (IsEmpty()) throw OutOfBounds(); x = top->data; Node<T> *p = top; top = top->link; delete p; return *this; }
try {ChainNode<T> *p = new ChainNode<T>;
delete p;
return false;}
catch (NoMem) {return true;}
}
• 笨拙! 信息技术科学学院
最新编辑ppt
23
H2.自定义的链表实现
template <class T> class Node {
catch (NoMem) {return true;} }
信息技术科学学院
最新编辑ppt
STM32堆栈分析
三、STM32堆栈区预备知识:一个由C/C++编译的程序占用的内存分为以下几个部分:●栈区(stack):编译器自动分配释放,存放函数的参数值,局部变量的值等。
操作方式类似于数据结构中的栈。
●堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
●全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
程序结束后由系统释放。
●文字常量区—常量字符串就是放在这里的。
程序结束后由系统释放●程序代码区—存放函数体的二进制代码编译后,各个区存储内容举例说明如下://main.cppint 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"优化成一个地方。
}STM32的分区STM32的分区从0x2000 0000(0x2000 0000是SRAM的起始地址,由此可知,堆栈等都是在RAM中的)开始。
静态区,堆,栈。
所有的全局变量,包括静态变量之类的,全部存储在静态存储区。
紧跟静态存储区之后的,是堆区(如没用到malloc,则没有该区),之后是栈区,栈在程序中存储局部变量。
先看启动文件startup_stm32f10x_md.s的定义:; Amount of memory (in bytes) allocated for Stack; Tailor this value to your application needs; <h> Stack Configuration; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Stack_Size EQU 0x00000400AREA STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem SPACE Stack_Size__initial_sp; <h> Heap Configuration; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Heap_Size EQU 0x00000200AREA HEAP, NOINIT, READWRITE, ALIGN=3__heap_baseHeap_Mem SPACE Heap_Size__heap_limit这里定义了堆栈各自大小,堆:512bytes 栈1k;所以栈区大小有限制,我们在局部变量中不要定义大数组否则容易溢出。
基于STM32分析栈、堆、全局区、常量区、代码区
基于STM32分析栈、堆、全局区、常量区、代码区在一个STM32程序代码中,从内存高地址到内存低地址,依次分布着栈区、堆区、全局区(静态区)、常量区、代码区,其中全局区中高地址分布着.bss段,低地址分布着.data段。
总的分布如下所示:内存高地址栈区堆区.bss段.data段常量区内存低地址代码区一、栈区(stack)临时创建的局部变量存放在栈区。
函数调用时,其入口参数存放在栈区。
函数返回时,其返回值存放在栈区。
const定义的局部变量存放在栈区。
2、堆区(heap)堆区用于存放程序运行中被动态分布的内存段,可增可减。
可以有malloc等函数实现动态分布内存。
有malloc函数分布的内存,必须用free进行内存释放,否则会造成内存泄漏。
3、全局区(静态区)全局区有.bss段和.data段组成,可读可写。
4、.bss段未初始化的全局变量存放在.bss段。
初始化为0的全局变量和初始化为0的静态变量存放在.bss段。
.bss段不占用可执行文件空间,其内容有操作系统初始化。
5、.data段已经初始化的全局变量存放在.data段。
静态变量存放在.data段。
.data段占用可执行文件空间,其内容有程序初始化。
const定义的全局变量存放在.rodata段。
6、常量区字符串存放在常量区。
常量区的内容不可以被修改。
7、代码区程序执行代码存放在代码区。
字符串常量也有可能存放在代码区。
通过上面的介绍,可能你对各个数据的存储位置还是很模糊,下面通过一个简单的程序,再来体会理解一下。
通过上面的介绍,可能你对各个数据的存储位置还是很模糊,下面通过一个简单的程序,再来体会理解一下【多余一段】#include <stdio.h>static unsigned int val1 = 1; //val1存放在.data段unsigned int val2 = 1; //初始化的全局变量存放在.data段unsigned int val3 ; //未初始化的全局变量存放在.bss段const unsigned int val4 = 1; //val4存放在.rodata(只读数据段)unsigned char Demo(unsigned int num) //num 存放在栈区{ char*var = "123456"; //var存放在栈区,"123456"存放在常量区unsigned int num1 = 1 ; //num1存放在栈区static unsigned int num2 = 0; //num2存放在.data段constunsigned int num3 = 7; //num3存放在栈区void*p; p = malloc(8); //p存放在堆区free(p); return1;}void main(){ unsigned int num = 0; num = Demo(num); //Demo()函数的返回值存放在栈区。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
详细解析STM32中的堆栈机制
刚拿到STM32时,你只编写一个死循环
编译后,就会发现这幺个程序已用了1600多的RAM,这要是在51单片机上,会心疼死了,这1600多的RAM跑哪儿去了,分析.map文件,你会发现是堆和栈占用的
在startup_stm32f10x_md.s文件中,它的前面几行就有以下定义:
这下明白了吧,STM32在启动的时候,RAM首先分配给使用到的全局变量,还有调用库占用的一些数据(不太清楚是什幺数据),然后再将剩余的空间分配给Heap和Stack。
由于内存空间是启动时实现分配好的,所以当动态分配内存的需求过多的时候,就会产生堆栈空间不足的问题。
查阅网上的资料,理解堆和栈的区别:
- (1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似于数据结构中的栈。