IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 单片机内存及运行 -> 正文阅读

[嵌入式]单片机内存及运行

单片机内存及运行

内存

一般单片机内存分为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的堆空间,那这时候就会内存泄漏。程序跑哪我也不知道了。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-06 11:19:00  更:2021-09-06 11:20:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:03:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码