找回密码
 注册
关于网站域名变更的通知
查看: 68|回复: 0
打印 上一主题 下一主题

STM32内存和堆栈

[复制链接]

该用户从未签到

跳转到指定楼层
1#
 楼主| 发表于 2024-6-3 16:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
内存基本构成
①  可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。
②  静态存储区:内存在程序编译的时候就已经分配好了,这块内存在程序的整个运行期间都存在。它主要存放静态变量、全局变量和常量。
③  栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率高,但是分配的内存容量有限。栈空间用于局部变量、函数调用、函数的参数等。
④  堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存,动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放动态内存。但是,良好的编程习惯是:如果某动态内存不在使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。(从内存区域的起始地址开始分配给各个全局变量和静态变量:0x200000004)

+ R# R/ i/ g/ ^7 p) ]
按照这个说法,在startup_stm32f10x_hd文件里面设置了:
Heap_Size     EQU  0x00000000

4 t# w  w4 k. g/ ]1 W+ y4 N
也就是没有任何动态内除分配。
这样,内存=静态存储区+栈区
不存在堆!!!!!
因为没有用malloc来动态分配内存,所以提到的一切堆区,其实就是静态内存区。
1 {( r4 M/ `! w* K7 k4 N% N( L' d* e
另外,经过测试,确实是这样。
STM32的内存分配,应该分为两种情况:
1、使用了系统的malloc;
2、未使用系统的malloc。

2 l+ i! y/ p4 e, H3 F2 ?! k0 l' [
第一种情况(使用malloc)
STM32的内存分配规律:从0x20000000开始依次为:静态存储区+堆区+栈区;
8 L) j, S/ \( x$ j# A2 |0 Z- o+ D8 G
第二种情况(不使用malloc)
STM32的内存分配规律:从0x20000000开始依次为:静态存储区+栈区;
7 J4 C5 l* N+ T( d2 \6 Q1 p
第二种情况不存在堆区
所以,一般对于开发板历程,实际上,没有所谓的堆区的概念,而仅仅是:静态存储区+栈区。无论哪种情况,所有的全局变量,包括静态变量之类的,全部存储在静态存储区。紧跟静态存储区之后的,是堆区(如没使用到malloc,则没有该区),之后是栈区。
此博文借鉴了原子哥的,发表此篇以此记录

( F& l% a9 \/ Z, m
补充知识:C语言
(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似于数据结构中的栈。(切记不要在函数里面放N多局部变量,尤其是大数组)
(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收,分配的方式类似于数据结构中的链表。
(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量在一块区域;未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统自动释放。
(4)文字常量区:常量字符串就是存放在这里的;
(5)程序代码区(ROM):存放函数体的二进制代码。
(6)堆是向上增长,栈是向下增长。
9 l" e. k5 G; L
//STM32查找栈增长方向,结果保存在stack_dir里面
+ ~, p% j; O& @! u5 R  a: C//0,向下增长;1,向上增长.
1 `- ]) l- Z! G" vstaticu8 stack_dir;4 K/ R+ E5 N" i9 t* |: h7 ~+ C
3 t# |0 i- z: w
//查找栈增长方向,结果保存在stack_dir里面.' r: W% V1 a, i) p3 `8 U' C- }
voidfind_stack_direction(void)/ \+ K8 D! [3 D& _, a7 G4 K/ l
{, @* \+ ^) N: ]2 T# H( A- a6 w8 F8 a" f+ @
   static u8 *addr=NULL; //用于存放第一个dummy的地址。3 \4 @! }) s' O- h0 L1 _' c# I# @. u
   u8dummy;              //用于获取栈地址
$ x2 i& a. h. u   if(addr==NULL)    //第一次进入
% I" b) Z8 {6 M( Y7 k" C& G& K8 i   {                          
0 R  ~+ W# f9 U8 D/ y       addr=&dummy;     //保存dummy的地址
4 |3 G2 r+ W& c: [( l       find_stack_direction ();  //递归
9 o2 S' a: ~- @) X2 Z! q   }else               //第二次进入
! o8 b- S! S/ ?$ ]1 g {  " y% r) z- `6 D3 t. Z9 G
       if(&dummy>addr)stack_dir=1; //第二次dummy的地址大于第一次dummy,那么说明栈增长方向是向上的.
! n+ S6 r# W- i; B$ \( N       else stack_dir=0;          //第二次dummy的地址小于第一次dummy,那么说明栈增长方向是向下的.  
5 E$ H# N. ?/ l9 S; N- k }& k& |; D5 p0 m' V- W  Y1 n. I! E
}
一般CPU的栈增长方向都是向下的
9 g5 Y) `$ ]9 ?
大端模式:低位字节存在高地址上,高位字节存在低地址上
4 K9 j! o! Z$ Y; o/ X小端模式:高位字节存在高地址上,低位字节存在低地址上
//CPU到底是大端还是小端,可以通过如下代码测试:
. }6 o% n" D" T9 A//CPU大小端
$ w! _+ ^6 T6 l, |//0,小端模式;1,大端模式.
5 M- ]0 p; F  E: f" ^static u8 cpu_endian;7 q* v3 }! w. j" ~
- e0 g/ w; h" |$ I( a. l; v
//获取CPU大小端模式,结果保存在cpu_endian里面
" q- A$ [& z; Evoid find_cpu_endian(void)
. W* g, @# U# _& K{ # _9 v2 W8 j3 u( T/ j  d  F
int x=1;7 M/ _9 c6 g/ m9 ^, N/ W; n
if(*(char*)&x==1)cpu_endian=0; //小端模式 ) J7 Y6 c2 ^; K' V6 m  K4 J7 f& ?  D
else cpu_endian=1;    //大端模式  ' O1 o# p; K/ s9 ?# E) {! F! k, a
}0 t( g5 O, j9 l. O) j
//以上测试,在STM32上,你会得到cpu_endian=0,也就是小端模式.

; {2 _: y- n! J- C8 j2 _
6 ~+ n) k1 V- }- [( ~# v' O: z, n4 ]6 F% j* o) P  i
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-19 21:27 , Processed in 0.109375 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表