关注+星标公众号,不错过精彩内容
( t* Y7 r* T2 J- n: w- q1 b
guizzzrcjhx64063131049.gif
/ g( h- y3 Q4 s7 n8 Z1 y; W作者 | 行墨" A E m6 N% b4 n- l) c
编排 | strongerHuang( M& a& t; f% s D
看到有小伙伴在讨论关于单片机内存的话题,今天就结合STM32给大家描述一下常见的划分区域。
% f( L( k3 g" f- \1 B# a' V在一个STM32程序代码中,从内存高地址到内存低地址,依次分布着栈区、堆区、全局区(静态区)、常量区、代码区,其中全局区中高地址分布着.bss段,低地址分布着.data段。2 Y! E7 K4 r$ v$ k" O8 B4 a
总的分布如下所示:内存高地址 | 栈区 |
) e6 z% C' A0 T) |/ B | 堆区 | .bss段 | .data段 | 常量区 | 内存低地址 | 代码区 |
) z2 R- X$ R8 b0 I/ `4 L- V9 K$ f一、栈区(stack)临时创建的局部变量存放在栈区。函数调用时,其入口参数存放在栈区。函数返回时,其返回值存放在栈区。const定义的局部变量存放在栈区。
4 T6 V! v8 V) M" |) H4 \% q* ]2、堆区(heap)堆区用于存放程序运行中被动态分布的内存段,可增可减。可以有malloc等函数实现动态分布内存。有malloc函数分布的内存,必须用free进行内存释放,否则会造成内存泄漏。" |/ m# [' C# B9 Z6 n7 S
3、全局区(静态区)全局区有.bss段和.data段组成,可读可写。
7 q% `: d4 r/ J, S0 {$ c4、.bss段未初始化的全局变量存放在.bss段。初始化为0的全局变量和初始化为0的静态变量存放在.bss段。.bss段不占用可执行文件空间,其内容有操作系统初始化。
+ }6 w1 v& B/ }- l5、.data段已经初始化的全局变量存放在.data段。静态变量存放在.data段。.data段占用可执行文件空间,其内容有程序初始化。const定义的全局变量存放在.rodata段。- _ k0 @/ R) \. ?# @% S
6、常量区字符串存放在常量区。常量区的内容不可以被修改。
4 N9 {8 e0 N9 O7、代码区程序执行代码存放在代码区。字符串常量也有可能存放在代码区。: D( g* Z3 w) D: r- a5 R
通过上面的介绍,可能你对各个数据的存储位置还是很模糊,下面通过一个简单的程序,再来体会理解一下。
: `6 {# y" k& z8 P" l通过上面的介绍,可能你对各个数据的存储位置还是很模糊,下面通过一个简单的程序,再来体会理解一下【多余一段】#include
+ m' J/ u/ l6 i+ V" s% [5 {static unsigned int val1 = 1; //val1存放在.data段unsigned int val2 = 1; //初始化的全局变量存放在.data段unsigned int val3 ; //未初始化的全局变量存放在.bss段const unsigned int val4 = 1; //val4存放在.rodata(只读数据段)6 }8 E" b7 M: y# O9 \9 d
unsigned char Demo(unsigned int num) //num 存放在栈区{ char var = "123456"; //var存放在栈区,"123456"存放在常量区 unsigned int num1 = 1 ; //num1存放在栈区 static unsigned int num2 = 0; //num2存放在.data段 const unsigned int num3 = 7; //num3存放在栈区 void *p; p = malloc(8); //p存放在堆区 free(p); return 1;}
8 b8 M# t( M/ F. Fvoid main(){ unsigned int num = 0 ; num = Demo(num); //Demo()函数的返回值存放在栈区。}: E* W* C/ L$ U( t$ Y
上面我们已经对堆、栈、全局区、常量区、代码区进行了全面的分析,也举例进行了说明。下面我们在对这些区存放在哪种介质上进行讨论。
2 d# V7 |$ n# M2 x- ?8、RAM和ROM、Flash Memory的物理特性首先,我们需要明白RAM和ROM、Flash Memory的物理特性。 ?( Y" o) I) n1 {
9、RAMRAM又称随机存取存储器,存储的内容可通过指令随机读写访问。RAM中的存储的数据在掉电是会丢失,因而只能在开机运行时存储数据。其中RAM又可以分为两种,一种是Dynamic RAM(DRAM动态随机存储器),另一种是Static RAM(SRAM,静态随机存储器)。
0 ~: f( c4 f* B- u7 I$ ?2 x' a10、ROMROM又称只读存储器,只能从里面读出数据而不能任意写入数据。ROM与RAM相比,具有读写速度慢的缺点。但由于其具有掉电后数据可保持不变的优点,因此常用也存放一次性写入的程序和数据,比如主版的BIOS程序的芯片就是ROM存储器。
0 f L$ L$ B5 H* Z" K11、Flash Memory由于ROM具有不易更改的特性,后面就发展了Flash Memory。Flash Memory不仅具有ROM掉电不丢失数据的特点,又可以在需要的时候对数据进行更改,不过价格比ROM要高。
0 U/ b; @, V) S: H* o12、不同数据的存放位置由前面的分析我们知道,代码区和常量区的内容是不允许被修改的,ROM(STM32就是Flash Memory)也是不允许被修改的,所以代码区和常量区的内容编译后存储在ROM中。; r0 n5 w3 c2 m/ _: I
而栈、堆、全局区(.bss段、.data段)都是存放在RAM中。
0 [( B$ h _4 }5 n6 C3 Y% s至此,关于不同数据存放哪个区域已经全部介绍完了。下面还将介绍一下Keil 的Build Output窗口。
" o- H B6 ^) i7 [* V- B; W13、Keil 的Build Output窗口; e1 ?8 \5 l4 K
s3javjcfx4u64063131149.png
* f2 T' A" X$ K1 K. M. c: a如上图,存在Code、RO-data、RW-data、ZI-data四个代码段大小。# c# a, [3 J, D- F9 \+ o
其中Code就是代码占用大小,RO-data是只读常量、RW-data是已初始化的可读可写变量,ZI-data是未初始化的可读可写变量。
) o D& z! }7 t0 R+ y7 w有些时候,我们需要知道RAM和ROM的使用情况如何,那么我们就可以使用下面的公式计算。
* F! [" X% E" z0 XRAM = RW-data + ZI-dataROM = Code + RO-data + RW-data 本文由作者『行墨』原创并授权发布,来源地址:https://blog.csdn.net/lin_duo/article/details/103019390------------ END ------------" N' v5 g! H$ V" y6 o
yppjguhgug564063131249.gif
, ^$ x1 g6 w+ t/ f
●专栏《嵌入式工具》●专栏《嵌入式开发》●专栏《Keil教程》●嵌入式专栏精选教程
: Q. }! i& U5 @! j关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。
" B/ Y$ O, H7 a9 e% _
/ g! S( W1 o$ H
pgzqdhp5yvg64063131349.png
- q h# t3 |/ T8 P4 K1 @点击“阅读原文”查看更多分享。 |