ARM嵌入式系统C语言编程.pdf
《ARM嵌入式系统C语言编程.pdf》由会员分享,可在线阅读,更多相关《ARM嵌入式系统C语言编程.pdf(3页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、收稿日期:2002-05-10。姜换新,硕士,主研领域:数字通信、嵌入式及网络编程。ARM嵌入式系统C语言编程姜 换 新(惠普中国软件研发中心 上海201206)摘 要 无操作系统支持的嵌入式系统软件,包括系统引导(BOOT)、驱动程序、动态内存管理、IO、通信以及应用软件等方面。本文详细介绍了嵌入式平台上用C语言编写系统软件和应用软件的方法。虽然是针对ARM平台介绍的,但基本经验和算法也适合于其他嵌入式平台的软件设计。关键词 嵌入式系统 软件 C语言 ARMPROGRAMMING C ON ARM EMBEDDED PLATFORMJiang Huanxin(China Software S
2、olutions Center,Hewlett-Packard Company,Shanghai 201206)AbstractProgramming C on ARM embedded platform is a complicated project.Modules including system boot,drivers,dynamic memory manage2ment,IO interface,communications and applications should be considered carefully.With an excellent experience on
3、 ARM embedded system,the au2thor gives a detailed description in this paper on the methods and algorithms about programming ARM.Though ARM is the only discussed item,thispaper is useful for programming on any other embedded platforms.KeywordsEmbedded systemSoftwareC programming languageARM1 引 言无操作系统
4、支持的嵌入式软件包括系统引导(BOOT)、外围驱动程序、存储管理、系统IO、通信、应用程序等方面,需要结合采用汇编语言(约占10%)和C语言(约占90%)。本文结合作者实践,详细介绍ARM嵌入式平台的C编程方法。考虑到通信软件涉及范围较大,本文不进行讨论。2 系统引导与main函数通常C语言是从main函数开始的。main函数的原型是:int main(int argc,char3 3argv)其中argc是参数的个数,argv是指向各参数的指针的数组。main函数由操作系统内核启动,操作系统内核完成函数所需的变量初始化工作,并在调用结束后检查main函数的返回值,若返回值为0,表明程序运行正
5、常,否则表明程序运行出错。在嵌入式系统中,由于没有操作系统内核存在,对main函数的初始化工作只能由系统引导(BOOT)模块完成。系统引导(BOOT)部分完成系统初始化工作,用汇编语言实现。它的工作包括硬件初始化、栈寄存器的设置、全局变量的初始化或清0、RAM中运行的模块的加载、堆参数的初始化等。完成这些工作后,再把控制权交给C的main函数。显然,对嵌入式系统的main而言,argc和argv这两个参数及返回值都是没有意义的(如果返回,表明系统出现严重错误)。另外,为了避免产生混淆,我们还必须给main函数另外取一个名字,比如Main。否则,编译器将会给main函数生成一大堆初始化代码,导致
6、C程序的主入口与系统引导模块的接口错误。系统引导模块完成各种初始化工作后,用一条跳转指令进入C的主入口Main,控制权从此移交给了C应用程序。3 存储管理存储管理是一个复杂的课题。从广义的角度来说,磁盘文件系统、内存、片内高速Cache等都属于这个范畴。嵌入式系统中,较有意义的是内存的动态分配与释放及Flash存储器管理两方面。本文要介绍的是我们在嵌入式系统中实现的动态内存管理。C语言中动态内存分配与释放主要由malloc和free两个标准库函数实现。malloc从系统空闲内存中分配合适的内存块,free函数完成内存块的回收。这两个函数一般需要操作系统内核的支持,在ARM裸平台上,不能直接调用
7、。为此,我们编写了malloc和mfree两个函数,实现动态存储管理的功能。典型应用程序内存映象分成代码区、数据区和栈区,三个区从低地址到高地址依次分布。代码区从最低地址开始,栈区51则占据最高地址。代码区和数据区可以相连,也可以分开。嵌入式系统里,代码区位于只读存储器(如Flash)中,数据区和栈区则位于RAM中,因此代码区和数据区一般并不相连1)。数据区和栈区是分开的,它们之间的空隙称作堆。堆作为一个连续的可利用空间,是系统的初始可分配块。每次应用程序申请内存,malloc便从堆中分割出一块(从低地址开始)给它。随着申请次数的增加,原来一个完整的内存块便被分割为多个独立的块分配给应用程序。
8、由于内存释放的先后顺序是随机的,因此一定时间后,系统中将存在多个互不相连的内存块。这就使得整个内存区呈现出占用块和空闲块犬牙交错的状态,如图1所示。图中灰色部分表示内存被占用,白色部分表示未被占用。图1 动态存储管理过程中的内存状态为了进行内存动态管理,需要维护两张全局表,一张是可利用空间表(availlist),管理空闲内存块的信息,另一张是已分配空间表(usedlist),管理占用内存块。这两张表都用双向循环链表实现。随着系统的运行,可利用空间表中往往会有多个空闲块存在,究竟分配哪一块呢?文1介绍了三种不同的分配策略,即首次拟合法、最佳拟合法和最差拟合法,各有优缺点。笔者实现的是首次拟合法
9、。可利用空间表和已分配空间表采用相同的“表元”数据结构,定义如下:struct mblockstruct mblock3next;struct mblock3prev;sizet size;char3space;在系统初始化时,整个可分配内存块是一个连续的存储区,可利用空间表的元素只有一个。malloc函数每次分配内存时,先检查size(malloc的参数)是否合法(如是否超出堆的范围),若合法,再将其与32-bit字对齐,然后从availlist中搜索合适的内存块,并将其分配给应用程序。如果内存块的大小比size大得较多,则对内存块进行分裂,低地址的一块分配给应用程序,高地址的一块仍然放入a
10、vaillist中。如果搜索不到合适的空闲块,malloc返回(void3)0。mfree函数释放内存时,根据参数addr给定的地址,在usedlist中搜索相应的表元,找到后,将它标识的内存块释放,并插入到availlist中去。然后,在availlist中检查是否有相邻的空闲块,并进行空闲块的合并。有三种不同的情况要分别处理:(1)左相邻:相邻块在当前释放块的低地址端。(2)右相邻:相邻块在当前释放块的高地址端。(3)左右相邻:当前释放块的低地址端和高地址端都有相邻块。在具体的分配算法上,文1介绍了边界标识法和伙伴系统。前者直接将链表管理信息插入到内存块的前端和后端,回收算法效率较高,但如
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ARM 嵌入式 系统 语言 编程
限制150内