文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>C语言程序运行在嵌入式中的方式

C语言程序运行在嵌入式中的方式

时间:2011-03-23  来源:☆&寒 烟☆

我们所做的程序最后都是要放到设备中运行的,鉴于嵌入式设备的特殊性,它的程序在运行方式上和PC机上还是有一些不同,今天就来给大家总结一下:

RAM调试运行:即在程序的调试阶段将主机的映像文件直接放置到目标系统的RAM中。此时,RAM既是程序的存储空间,也是程序的运行空间。

    在嵌入式系统中,这是一种常用的调试方式(非通常的运行方式)。在通常的运行方式下,程序运行的起始地址一般不可能是RAM。RAM在掉电之后内容会丢失,因此系统上电的时候,RAM中一般不会有有效的程序。但是在程序的调试阶段,可以将程序直接载入RAM,然后在RAM的程序载入地址处运行程序。下图是嵌入式系统RAM中的调试程序的内存布局:

  

     这是一种相对简单的形式,因为代码段的存储地址和运行地址是相同的,都是RAM(SDRAM或者SRAM)中的地址。在这种情况下,程序没有运行初始化阶段加载的问题。 从主机向目标机载入程序的时候,程序映像文件中代码段(code或text)、只读数据段、读写数据段依次载入目标系统RAM(SDRAM或者SRAM)的空间中。程序载入到目标机之后,将从代码区的地址开始运行,在运行的初始化阶段,将开辟未初始化数据区,并将其初始化为0,在运行时将动态开辟堆区和栈区。

     在没有操作系统的情况下,开辟内存的工作都是由编译器生成的代码完成的,实现的原理是在映像文件中加入这些代码。主要工作包括:在程序运行时根据实际大小开辟未初始化的数据段;初始化栈区的指针,这个指针和物理内存的实际大小有关;在调用相关函数(malloc、free)时使用堆区,这些函数一般由调用库函数实现。下表列出了C语言程序在RAM中的调试过程。

阶段

涉及的部分

主要工作

程序的映像

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

将程序放置在RAM中

初始化阶段

未初始化数据段(BSS)

开辟BSS段 并且清零

运行阶段

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

未初始化数据段(BSS)

堆(heap)

栈(stack)

运行RAM代 码段中的程序,动态地在RAM中开辟堆和栈

小结:程序直接载入RAM运行时,程序的加载位置和运行位置是一致的,因此不存在段复制的问题,需要在初始化阶段开辟未初始化区 域,在运行时使用堆栈。

固化程序的XIP运行:固化应用是一种嵌入式系统常用的运行方式,其前提是目标代码位于目标系统ROM(Flash)中。ROM中的区域包括映像文件的代码段(code或text)、只读数据段(RO Data)、读写数据段(RW Data),如下图所示:

 

     代码的运行也是在ROM(Flash)中,因此,在编译过程中代码的存储地址和运行地址是相同的,由于上电时需要启动,因此该代码的位置一般是(0x0)。 在这种应用中,一件重要的事情就是将已初始化读写段的数据从Flash中复制到SDRAM中,由于已初始化读写段既需要固化,也需要在运行时修改,因此这一步是必须有的,在程序的初始化阶段需要完成这一步。

     一般来说,在编译过程中需要定义读写段和未初始化段的地址。在程序中可获取这些地址,然后就可以在程序的中加入复制的代码,实现读写段的转移。下表列出了C语言程序的XIP运行过程:

阶 段

涉及的部分

主要工作

程序的映像

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

程序 放置在Flash中

初始化阶段

读写数据段(RW Data)

未初始化数据段(BSS)

复制 读写数据段到RAM中

开辟 未初始化段并且清零

运行阶段

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

未初始化数据段(BSS)

堆(heap)

栈(stack)

运行Flash代 码段中的程序,动态地在RAM中开辟堆和栈

小结:程序在ROM或者Flash中以XIP形式运行的时候,不需要复制代码段和只读数据段,但是需要在RAM中复制读写数据 段,并另辟未初始化数据段。

固化程序的加载运行:在某些时候,在存放程序的位置是不能运行程序的,例如程序存储在不能以XIP方式运行的Nand-Flash或者硬盘中,在这种情况下,必须将程序完全加载到RAM中才可以运行。固化程序加载运行的内存布局如下图所示:

  

     依照这种方式运行程序,需要将Flash中所有的内容全部复制到SDRAM或者SRAM中。在一般情况 下,SDRAM或者SRAM的速度要快于Flash。这样做的另外一个好处是可以加快程序的运行速度。也就是说,即使Flash可以运行程序,将程序加载 到RAM中运行也还有一定的优势。

     这样做也产生了另外一个问题:代码段的载入地址和运行地址是不相同的,载入地址是在ROM(Flash)中, 但是运行的地址是在RAM(SDRAM或者SRAM)中。对于这个问题,不同的系统在加载程序的时候有不同的解决方式。

C语言固化程序的加载运行过程如下表所示:

阶 段

涉及的部分

主要工作

代码的映像

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

将程 序放置在Flash中

初始化阶段

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

未初始化数据段(BSS)

加载 代码段和只读数据段到RAM中

复制 读写数据段到RAM中

开辟 未初始化段并且清零

运行阶段

代码段(Code)

只读数据段(RO Data)

读写数据段(RW Data)

未初始化数据段(BSS)

堆(heap)

栈(stack)

运行RAM代 码段中的程序,动态地在RAM中开辟堆和栈

小结:固化程序在加载运行时,需要复制代码段、只读数据段和读写数据段到RAM中,并另辟未初始化数据段,然后在RAM中运行程序(执行代码段)。

以这种加载方式的运行程序,另外一个重要的问题是:如何把代码移到RAM中。在有操作系统的情况下,代码的复制工作是由操作系统完成的,在没有操作系统的情况下,处理方式相对复杂,程序需要自我复制。显然,这种方式实现的前提是代码最初放置在可以以XIP方式执行的内存中。

     程序本身复制的过程也是需要通过程序代码完成的,这时需要程序中的代码根据将包含自己的程序从ROM或者Flash中复制到RAM中。这是一个比较复杂的过程,程序的最前面部分是具有复制功能的代 码。系统上电后,从ROM或者Flash起始地址运行,具有复制功能的代码将全部代码段和其他需要复制的部分复制到RAM中,然后跳转到RAM中重新运行程序。

固化程序加载复制和跳转过程如下图所示。

在代码的前面一小部分是初始化的内容,这部分内容中有一部分是复制程序,这段复制程序将代码段复制至RAM中,当这段初始化程序运行完成后,将跳转到RAM中的某个地址运行。

注:本篇文章参考了电子工业出版社的《嵌入式Linux上的C语言编程实践一书》,在这里对本书作者再次表示感谢。

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载