ARM Cortex-M底层技术(1)—程序在Flash和SRAM的空间分配
1. keil编译介绍
当使用keil进行单片机的开发时,运行一段程序后,在output输出框会看到如下图的结果。
图1 keil 的output框
其中,Compiler编译器,使用的版本是 V5.06,程序会先经过编译、后链接linking生成可执行的代码,如果要下载单片机的Flash上,还需要转换成二进制(bin)或者十六进制(hex)的文件。具体过程如下:
图2 keil的编译过程
值得注意的是,经过编译后,并不会给变量赋地址(.o文件),只有经过链接器链接后变量才有地址,链接的作用可以看做是便于管理而做的分类,在链接阶段起作用的是分散加载文件,分散加载文件用来描述生成映像文件时所需的信息,即通过分散加载文件指定ARM链接器在链接阶段如何分配Code、RO-data、RW-data、ZI-data的地址,只用使用了分散加载文件后,你程序的变量、函数等数据才会有地址,只有如此做,程序在运行时,才能根据分配的地址去下一步执行程序,分散加载文件后面会详细讲解,这里只初步了解一下就可以。经链接后代码分为Code、RO-data、RW-data、ZI-data四部分。接下来是老生常谈的问题,每个区都是干嘛的呢?
- CODE:代码区,指程序中代码即函数体的大小,注意程序中未使用的函数也会算在CODE中,也即会占用FLASH空间,因此不用的函数最好删除掉,以免占用过多FLASH空间;
- RO-DATA:RO就是只读的意思,程序中只读的变量(也就是带Const的)和已初始化的字符串等;
- RW-DATA:特指已初始化的可读可写全局/静态变量;
- ZI-DATA:未初始化的可读可写全局/静态变量,注意初始化为0也算做未初始化,用到的堆空间和栈空间也会被算入这里面;
之前我一直在想的一个问题是我的局部变量存放在哪里,其实是这样的,局部变量只有在程序运行的过程中才会生成,当程序不运行,即将关闭单片机的电源后,是没有局部变量的。所以这就要涉及到程序的两种状态存储态和运行态。
图3 程序的存储态和运行态
存储态:向Flash中下载程序时,其实仅仅下载的是CODE+RO-data+RW-data的内容,意思就是说,在掉电情况下,Flash里面的内存仅包含CODE+RO-data+RW-data这三块。
运行态:当上电后,程序运行时,首先程序会从特定的地址进行启动,下一节我会详细分析启动文件,启动时会将RW-data的数据加载到SRAM中(启用文件中有一段代码是干这件事的,说的在具体点是分散加载文件会做这件事,在默认情况下,keil中的链接器armlink工具(D:\Keil_v526\ARM\ARMCC\bin\armlink.exe)已经帮你做完了这件事),单片机的 RO区域不需要加载到 SRAM,内核直接从 FLASH 读取指令运行。那ZI-data的数据怎么办呢?对于初始值为0全局变量来说,因为要在Code区要调用该全局变量,所以肯定要对其进行描述,程序运行时就知道了,原来你是初始值为0的全局变量呀,然后分散加载文件就在SRAM中给它分配了一段固定区域的地址;对于局部变量来说, 会自动分配大小,不用我们管。RW-DATA+ZI-DATA就是程序运行总共会占用SRAM的长度,为什么说总共呢?因为当某一个函数运行完后,在这个函数内部的局部变量会被释放掉。再次强调一下,生成局部变量的栈空间包含在ZI-data区的范围。
图4 程序的组成
计算机系统的应用程序运行过程很类似,不过计算机系统的程序在存储状态时位于硬盘,执行的时候甚至会把上述的 RO 区域(代码、只读数据)加载到内存,加快运行速度,还有虚拟内存管理单元(MMU)辅助加载数据,使得可以运行比物理内存还大的应用程序,因为单片机中没有MMU,所以无法支持 Linux 和 Windows 系统,这里我说的单片是指M系列的单片机,但是可以跑ucos或FreeRTOS系统。
2. Flash和Sram的理解
存储器是计算机结构的重要组成部分,存储器是用来存储程序代码和数据的部件,有了存储器计算机才具有记忆功能。按照存储介质的特性,可以分“易失性存储器”和“非易失性存储器”两类,易失和非易失是指存储器断电后,里面存储的内容是否会丢失,另一边的速度而言呢,易失性存储器的速度要快于非易失性存储器。
2.1 易失性存储器
按照RAM的物理存储机制,可以分为DRAM(Dynamic)和SRAM(Static)两类。首先,说一下目前所用的DRAM,其通讯时序是利用时钟进行同步通讯,所以起名为Synchronous DRAM,那么,后期为了进一步提高SDRAM的通讯速度,人们设计了DDR SDRAM存储器(Double Data Rate SDRAM),随后又发展出二、三、四代SDRAM,现在很多PC机上的内存条是DDRIII SDRAM存储器。另外,静态随机存储器SRAM的存储单元以锁存器来存储数据,结构比DRAM要复杂很多,所以生产相同容量的存储器,DRAM的成本要更低,且集成度更高。这里我只讲基本概念,怎么去操作这些易失性存储器需要可以自行查找资料分析。
2.2 非易失性存储器
半导体类的非易失性存储器有ROM和FLASH,感觉现在ROM使用的比较少了,貌似很多都被flash代替了。之前学单片机的时候,用的外接EEPROM算是一种ROM,不作过多介绍。FLASH的容量一般比EEPROM大得多,且在擦除时,一般以多个字节为单位。如有的FLASH存储器以4096个字节为扇区,最小的擦除单位为一个扇区,有的也称作页page。根据存储单元电路的不同,FLASH存储器又分为NOR FLASH和NAND FLASH。
NOR与NAND的共性是在数据写入前都需要有擦除操作,而擦除操作一般是以“扇区/块”为单位,而NOR与NAND特性的差别,主要是其内部“地址/数据线”是否分开导致的。
- 由于NOR的地址线和数据线分开,它可以按“字节”读写数据,符合CPU的指令译码执行要求,所以假如NOR上存储了代码指令,CPU给NOR一个地址,NOR就能向CPU返回一个数据让CPU执行,中间不需要额外的处理操作。所以,在功能上可以认为NOR是一种断电后数据不丢失的RAM,但它的擦除单位与RAM有区别,且读写速度比RAM要慢得多。
- 由于NAND的数据和地址线共用,只能按“块”来读写数据,假如NAND上存储了代码指令,CPU给NAND地址后,它无法直接返回该地址的数据,所以不符合指令译码要求。若代码存储在NAND上,可以把它先加载到RAM存储器上,再由CPU执行。
目前,单片机SOC内部普遍使用的是SRAM和NorFlash。如果记不住,只需要知道,不跑linux操作系统的Flash全部是norflash,但是不绝对。
Flash,SRAM寄存器和输入输出端口被组织在同一个4GB的线性地址空间内,可访问的存储器空间被分成8个主要块,每个块为512MB。存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射,如果给存储器再分配一个地址就叫存储器重映射。NRF52832的内存映射如下图所示,
在nordic芯片中FLASH存储编译后下载的程序,SRAM是存储在程序运行中的临时创建数据(ARMv7,哈弗结构),故只要你不外扩存储器,写完的程序中只要在芯片上运行起来,所有数据也就会出现在这两个存储器中。Flsah或者Ram内部又会根据不同的功能把他们分为多个模块。
在网上看到一张图,感觉很有意思。这张图是STM32程序下载到Flash上的存储结构。如果你知道了这些具体地址,及地址块的作用,就可以做BootLoader以便产品后期升级。具体分析写Bootloader以及怎么分析这些地址,会在以后的分散加载文件中详细讲解。
参考网址:https://www.cnblogs.com/amanlikethis/p/3719529.html
ARM Cortex-M底层技术(1)—程序在Flash和SRAM的空间分配的更多相关文章
- ARM Cortex-M底层技术(2)—启动代码详解
杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第 ...
- ARM Cortex M3(V7-M架构)硬件启动程序 一
Cortex-m3启动代码分析笔记 启动代码文件名是STM32F10X.S,它的作用先总结下,然后再分析. 启动代码作用一般是: 1)堆和栈的初始化: 2)中断向量表定义: 3)地址重映射及中断向量表 ...
- ARM Cortex-M底层技术(3)—编译内核的原理及其应用
概述: 当前开发中,我使用的Keil开发工具较多(keil526),故以keil为例进行介绍,其他开发环境大同小异. 1. 编译链接的定义 不管我们编写的代码有多么简单,都必须经过「编译 --> ...
- 灵动微电子ARM Cortex M0 MM32F0010 GPIO 的配置驱动LED灯
灵动微电子ARM Cortex M0 MM32F0010 GPIO的配置 目录: 1.前言 2.学习方法简要说明 3.要点提示 4.注意事项 5.MM32F0010系统时钟的配置 6.MM32F001 ...
- 支撑Java NIO 与 NodeJS的底层技术
支撑Java NIO 与 NodeJS的底层技术 众所周知在近几个版本的Java中增加了一些对Java NIO.NIO2的支持,与此同时NodeJS技术栈中最为人称道的优势之一就是其高性能IO,那么我 ...
- AOP 底层技术比较
表 1. AOP 底层技术比较 AOP 底层技术 功能 性能 面向接口编程 编程难度 直接改写 class 文件 完全控制类 无明显性能代价 不要求 高,要求对 class 文件结构和 Java 字节 ...
- 计算机世界的道(C/ASM)生一(OS),一生二(API),二生万象(MFC/COM)——学包装技术的程序员将来会损失比较大,因为不了解本质,一旦包装过时就会被淘汰
道生一,一生二,二生万象.OO的思想就是抽象,万象归宗,化繁为简.99%的程序员使用OO,或者所谓的类库的目的就是好用,不必了解内部实现就可以直接达到所期望的结果.这时一种生产力的进步,一种流水线式半 ...
- Java技术开发程序员如果在2019年立足
2019年的互联网环境相对以往来说要更复杂一些,互联网领域也正在经历从消费互联网向产业互联网转型的阵痛期.其实不少公司从2018年开始已经在陆续进行结构化调整,这些调整中的重要内容就是岗位调整,而岗位 ...
- 云计算底层技术-虚拟网络设备(Bridge,VLAN)( 转发)
云计算底层技术-虚拟网络设备(Bridge,VLAN) Posted on September 24, 2017 by opengers in openstack openstack底层技术-各种虚拟 ...
随机推荐
- XDebug安装配置教程
笔者的开发环境如下:Windows8.1+Apache+PhpStorm+XDebug+Firefox(XDebug helper 1.4.3插件). 转载http://www.jb51.net/ar ...
- 1443:【例题4】Addition Chains
1443:[例题4]Addition Chains 题解 注释在代码里 注意优化搜索顺序以及最优化剪枝 代码 #include<iostream> #include<cstdio&g ...
- 二、启动一款app演示
一.下载aapt包 1. aapt即Android Asset Packaging Tool,在SDK的build-tools目录下.该工具可以查看apk包名和launcherActivity 2.打 ...
- word中打字会覆盖下一个字
insert键 误按了insert键,此时Word默认为改写模式,输入文本会覆盖后面的内容.
- 用JS实现移动的窗口
https://blog.csdn.net/iteye_21064/article/details/81496640 用JS实现移动的窗口 2007年09月06日 23:23:00 阅读数:3 很简单 ...
- apue 在 mac 环境编译错误
参考资料:https://unix.stackexchange.com/questions/105483/compiling-code-from-apue 笔者使用 mac 学习 apue, 在编译的 ...
- VS Code 使用Git进行版本控制
在Windows上安装Git:msysgit是Windows版的Git,从https://git-for-windows.github.io下载 Git安装到环境变量里,确保任意路径可以访问:将git ...
- 使用Inception-v3进行图像分类
https://blog.csdn.net/sinat_27382047/article/details/80534234 https://www.jianshu.com/p/cc830a6ed54b ...
- Oracle 高版本往低版本备份恢复的方法
1. 高版本的数据库备份恢复到低版本的数据库 有时候回报错, 提示version版本不一致, 2. 其实方法是expdp 导出的时候 增加一个参数就可以了 参数 一般的类型是 version=11.2 ...
- JSP总结(jsp/EL表达式/核心标签)
1.概念 jsp,即java Server Pages,java服务器页面. 2.简单介绍 小示例 <%@ page language="java" contentType= ...