首先说一下 mcu 的存储器组织。
蒙圈,mcu 中常使用的存储器类型有:flash、ram、rom(包括eeprom)
在软件角度来看,程序和数据的存储分为以下几个部分:
注:
1.代码段和常量段都可以用于保存常量数据,其主要区别是,如果常量可以作为汇编指令的一个操作数,则该常量被编译进代码段。如果不能用一个汇编操作数表示,则存于常量段。如 uchar a=0x05; 中的 0x05 将被编译成代码 mov #0x05, a;如果是 uchar a[]={0x05, 0x06} 则 0x05,0x06 被放置于常量段, 在初始化 a[] 的时候会有一段汇编指令用于将常量段中的内容拷贝到 a[] 中。
软件存储区与硬件存储器类型是怎么对应的呢?
一般来讲如下:
注:
1.mcu 中的 rom 通常用于存储制造商信息、控制器型号等信息;
2.对于 x86 体系结构的系统,因为没有 flash 类型的存储器,所以,所有的软件存储区最终都加载到内存中,但是其内存是分段的,用户对不同内存段的访问权限不同,其代码段和常量段不可以被用户修改,如果意外修改则抛出段错误异常。
知道了存储器类型和各存储区的划分之后,让我们来看以下三组程序:
1.
staticvoidprocstr(void)
{
ucharstr[]={12345};
}
这段程序中,str[] 是一个局部数组,其大小为 6,占用的堆栈空间是 2 个字符;12345 是常量,被存储在常量段;str[] 的初始化过程,相当于从常量区拷贝 6 个字符的数据到栈中,这 6 个字符是12345\0。
2.
staticvoidprocstr(void)
{
ucharstr[]=12345;
}
这段程序中,str[] 是一个局部数组,其大小为 6,占用的堆栈空间是 2 个字符;12345 是常量,被存储在常量段;str[] 的初始化过程,相当于从常量区拷贝 6 个字符的数据到栈中,这 6 个字符是 12345\0。
3.
staticvoidprocstr(void)
{
constuchar*str=12345;
}
这段程序中没有数组,唯一的str 是一个局部指针,其大小为 4(在 32 位系统中),因此这段程序只占用 4(在 32 位系统中)个字符的堆栈空间;12345是常量,被存储在常量段;str 的初始化过程,是将指针str 初始化为常量12345的地址,后续程序通过指针str直接访问常量段,无需内存拷贝过程。
从以上分析可以看出,前两种方法是一样的,都需要为局部数据分配存储空间,并将静态存储区的数据拷贝过来,而最后一种方法是通过指针直接访问静态数据而无需拷贝。如果字符串长度大于系统中指针的长度,第三种方法将在时间和空间上大大优于前两种方法(第三种方法极大的节省了堆栈空间,并减少了拷贝数据所用的时间)。
但是,对于 mcu 来说,并不总是第三种方法好,原因在于第三种方法是直接访问常量段,由上面的表可知,对于将常量存储于 flash 的 mcu 来说,访问常量段要比访问 ram 慢得多。因此,如果接下来要频繁访问这个字符串,那么,采用前两种方法在速度上将会更优一些,理由是前两种方法只需要访问一次 flash,而第三种方法则每次都需要访问 flash。
当然,如果在接下来的程序中,需要修改字符串str 中的内容,那就只能采用前两种方法,第三种方法将会提示错误。
特殊说明:今天讲的一些内容跟编译器的特性相关,不同编译器,甚至相同编译器的不同版本间存在一定差异。
利用易控组态软件构建全虚拟PLC控制系统的方法以及应用
用户界面在工业IoT自动化中的应用
小米5s plus伪开箱加跑分测试,给感兴趣的朋友
工信部发布5G+工业互联网十个典型应用场景和五个重点行业实践情况
微系统集成封装开拓差异化技术创新新领域
MCU的存储器组织知识
基于s3c2410的任务切换软中断级服务的实现
Zigbee信标、信标帧的作用和信标模式的设置
声音传感器输入/输出设备
宁德时代斥资74亿投资建设动力及储能锂电池研发与生产项目
物联网或带动市场大量布署远程与无线传感器节点
人工智能、区块链、算法...这30个大数据热词你知道吗
国内最大的5G智能电网在青岛落地
英特尔Stratix 10 GX 10M FPGA原型设计系统
车载摄像头UV胶防水密封用胶方案的简单说明
国内5G终端渗透率不断提升
高低温试验箱的安装要求有哪些
FPGA它都具备着什么样的优势
谈谈电路中的“地”
PLC实现自动化立体仓库系统