单片机内存及运行

单片机内存及运行

内存

一般单片机内存分为RAM和FLASH。
比如STM32F103ZET6

/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K
}

RAM

随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。

FLASH

快闪存储器(英语:flash memory),是一种电子式可清除程序化只读存储器的形式,允许在操作中被多次擦或写的存储器。

关键字

RAM可随时读写
FLASH只读。
这里说的读写是针对CPU的。

程序

1 int gvar_x;
2 int main(void)
3 {
4   	
5   	while (1)
6  		{
7   		gvar_x = gvar_x + 1;
8		}
9}

在代码7行,分别对变量gvar_x进行了写入操作。根据上面RAM、FLASH的介绍,写入操作只能在RAM中进行。
打开MAP文件,会发现:

.text.main     0x8000268       0x28 ./Core/Src/main.o
                0x8000268                main
.data.gvar_x   0x20000000        0x4 ./Core/Src/main.o
                0x20000000                gvar_x

可以看出gvar_x作为可写的变量被放到了RAM区域,而main函数作为只读的代码指令放到了只读的FLASH区域。

	  gvar_x = gvar_x+1;
 8000278:	4b02      	ldr	r3, [pc, #8]	; (8000284 <main+0x1c>)
 800027a:	681b      	ldr	r3, [r3, #0]
 800027c:	3301      	adds	r3, #1
 800027e:	4a01      	ldr	r2, [pc, #4]	; (8000284 <main+0x1c>)
 8000280:	6013      	str	r3, [r2, #0]
 8000282:	e7f9      	b.n	8000278 <main+0x10>
 8000284:	20000000 	.word	0x20000000

再来分析下汇编。

  1. 在地址8000278处,指令ldr r3, [pc, #8]意味着将PC+8处的数据加载到r3寄存器,从汇编可以看出PC+8=8000284,即将20000000加载到r3寄存器。
  2. 然后CPU继续运行来到800027a处,指令ldr r3, [r3, #0]意味着将r3+0处的数据加载到r3,而这时候r3的内容是20000000,也就是将20000000里面的数据加载到r3寄存器里面,这时候r3寄存器里面才是变量gvar_x的值。
  3. 在地址800027c处,指令adds r3, #1意味着对r3寄存器加1,也就是gvar_x+1。
  4. 到这一步就完成了,先取变量gvar_x的值,然后对变量gvar_x加1。
  5. 在地址800027e处,指令ldr r2, [pc, #4]意味着将PC+4,也就是8000284处的数据加载到r2寄存器里面,这里和第1步一样,先拿到变量gvar_x的地址。只不过r3已经被占用了,所以使用了r2寄存器,这里CPU自有一套标准选择使用的寄存器。
  6. 来到8000280处,指令str r3, [r2, #0]意味着将r3寄存器里的值设置到r2+0地址处,也就是20000000这个地址里面。

从上面流程可以看出,为什么不写到8000284处,还要绕一圈写道到20000000处,就是因为8000284属于FLASH,只可读,20000000属于RAM可读可写。如果FLASH里面的可写,那对程序来说就是一场灾难。
所以这就是单片机里面为什么要有只读的FLASH和可读可写的RAM。
从上面分析也可以看出,CPU执行代码指令是直接从FLASH里面直接取代码指令去执行。

RAM扩展

RAM里面有全局变量、静态变量、堆、栈。
在这里插入图片描述
当你编译完后,你写的代码指令和数据都在一个hex文件里面,而这个hex的起始地址是80000000开始的,也就是当你烧录程序时候,不会把变量烧录到20000000后面的地址。
那变量是什么时候到20000000里面的呢?
就在程序启动之前,CPU会先把属于RAM的数据变量都加载到RAM里面。
这就涉及VMA、LMA。也就是运行内存地址和加载内存地址。
这就是为什么当你的单片机掉电后,运行数据都丢失的原因。
如果你想保存这些数据,就需要单片机的外设FLASH模块了。而CPU是不能直接将数据写入到FLASH里面的。

_Min_Stack_Size = 0x400 ; /* required amount of stack */

栈里面就是存储的局部变量,当然栈是有大小的,这里最小设置的1KBytes。
假如堆+全局变量+静态变量使用了63K,那你栈只能使用1K空间,如果这时候你有个局部变量数据,大小是2K,那你就去HardFault里面呆着吧。

_Min_Heap_Size = 0x200 ; /* required amount of heap */

堆就是你程序在跑的过程中使用malloc开辟的空间。
假如栈+全局变量+静态变量使用了63K,而你又要开辟了一个2K的堆空间,那这时候就会内存泄漏。程序跑哪我也不知道了。

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值