转自:http://blog.sina.com.cn/s/blog_67ed0acc01014jyz.html
博主:(被转的博文的博主的头像,阳光一米啊~~~)
提到“程序”,大家首先想到的是肯定是我们自己所书写的一行行代码,如C代码、汇编代码。然而,我们仅仅知道这些还是不够的。相信现在学习嵌入式的朋友们,肯定多多少少有一些计算机、单片机的基础知识,计算机(我们常说的INTEL和AMD的CPU)也好,单片机(如8051)也好,他们可不认识我们所写的“代码”,这就像我们和一个不懂“汉语”的外国人说中文一样,他根本不会理解你说的是什么。
CPU所能认识的只是二进制的机器码,通常以.bin结尾,而我们所书写的代码(以C语言为例)被我们称为源文件,通常以.c结尾。这时,就有一个问题摆在我们面前了。在现实生活中,如果遇到外国人,我们可以请一个翻译将我们讲的中文翻译成外语,这样就达到了沟通的目的,而在嵌入式这个特殊领域里,我们也可以找一个“翻译”,它就是----编译器。
编译器的工作就像翻译一样,将我们写的源文件:C代码和汇编代码翻译成CPU所认识的二进制文件,这样CPU就可以执行我们的指令了。注意:在我们现在所用到的编译器通常指预编译器、编译器、汇编器、链接器和反汇编器这些工具的总和,这些工具各自起到不同的作用,在后续的文章中,会一一讲解。这里读者需要理解可执行程序的形成过程:
上图是孙鑫老师的C++课程中课件截图,C++程序和我们现在学习的C程序编译的过程原理是一样的,请大家深入理解。
相信从WINDOWS转向LINUX的程序员都会抱怨,WINDOWS中集成开发平台多的让人眼花,而LINUX至今大部分人还是使用命令行的方式去编辑,编译程序,麻烦得要命。其实LINUX中也有很好的集成开发平台,在我们装好的Fedora中系统自带的一个Eclipse就是一个很典型的开发平台,另外GNU还为我们提供了很多集成开发平台,如KDevelop,只不过目前,大部分LINUX程序员(至少从事嵌入式开发的)还是比较习惯使用古老和命令行开发模式。
这里,我也推荐大家使用命令行的开发模式,初学肯定会遇到困难,不过同样也会有好处的,这样更容易让初学者理解程序的运行机制。
在我们以后的学习中,我们使用的是交叉编译器,arm-linux- ,这里推荐使用天嵌已制作好的,当大家入门后,可以自己制作编译器。之所以称为交叉编译器,是因为,我们在PC机上编辑代码,编译、链接最后形成在ARM平台下执行的程序。(注:x86体系下的编译器为GCC,大家可自行参考GCC手册)
但这点要特别注意:大家一定要安装3.4.5版本,因为我们这里使用编译器主要编译裸奔程序,天嵌提供的另一版本4.3.3对裸奔程序支持不好。具体的安装方法详细天嵌的教程手册:
“TQ2440开发板使用手册V2.5_20100611.pdf”第85页。
这里只简单介绍该命令的使用方法,详细资料可详读参考资料中的《嵌入式LINUX应用开发完全手册》第3章。
-c 对源文件进行预处理、编译、汇编,但不做链接,生成中间OBJ文件,通常以.o结尾。
-g
-o 指定输出文件。如果不指定-o filename
B.
-Ttext
-Tdada
-Tbss
其中-T选项用来指定代码段、数据段、BSS段的起始地址。此外,还可以用来指定的链接脚本。本章中不涉及链接脚本,后续会详述。
知识点: 可执行程序是由代码段、数据段、BSS段组成的。 数据段:存放的是初始化的全局变量和静态变量。 BSS段:存放的是未初始化的全局变量和静态变量。 |
C. arm-linux-objcopy
用于将一个目标文件复制到另一个文件内,可以使用不同于源文件的格式输出到目的文件。常用于格式转化。
-O
-I
-S 不从源文件中复制重定位信息和符号信息到目标文件
D. arm-linux-objdump
用于显示二进制文件住处。常用于进行反汇编,方便调试。
-D 反汇编所有段
-m 指定反汇编目标文件所使用的架构,如
-b
2. Makefile
关于Makfile要介绍的实在是太多了,这里仅简单进行说明,请大家参考《GNU makefile 手册》。
目标(target)……. :
这里需要注意的是命令前面一定要使用TAB键,不能用空格。请参照后面的实例进行学习,看手册不要看得太多,要边学边用,这样才会达到最好的效果。
TQ2440开发板使用的是S3C2440 CPU,请大家学习本章的同时,参看S3C2440手册。
S3C2440有130复用I/O口。从GPA~~GPJ,其中需要注意的是没有GPI端口。这些端口和单片机的P0~P3口十分相似,初学者可以完成“当成”是单片机的IO口来操作。
为了点亮我们开发板的LED,我们参考一下天嵌开板的原理图。
上述原理图分别取自于核心板原理图和扩展板原理图。上图表明,4个LED连接在CPU的GPB5、6、7、8端口,而且是共阳的连接方式,如果要使其点亮,我们应该在这些端口中输出“0”。
2.GPIO寄存器简介
请大家参看手册。
GPIO引脚是通过寄存器来操纵的,由于GPIO引脚大部分都是复用功能,除了通用的I/O端口外,还有其它的功能,在上图中可以看出,GPB5还有一个名称叫“nXBACK”,因此,我们需要一个寄存器来选择它是通用的I/O功能还是额外的功能,这个寄存器就叫GPBCON。
除了GPBCON,GPB端口还有两个寄存器:GPBDAT,GPBUP。GPBDAT用于确定引脚的电平状态,当读操作时,读该寄存器就可以知道引脚是高电平或低电平;当写操作时,向寄存器中写0或1 ,就可以操纵引脚了。
三个寄存器的地址:
GPBCON
GPBDAT
GPBUP
3.实例分析
下面列举出的是韦东山老师的代码:
@******************************************************************************
@ File:led_on.S
@
@******************************************************************************
.text
.global _start
_start:
MAIN_LOOP:
除了韦东山老师的注释,我又增加了一些,如果看这段程序还吃力的同学,请查阅《ARM体系结构与编程》中的相关章节,请注意,只要看懂上述代码即可,不求将所有的指令全掌握。
上述代码只是源文件,我们还需将其编译成可执行的.BIN文件,请看下面的Makefile文件。
led_on.bin : led_on.S
clean: