Chinaunix首页 | 论坛 | 博客
  • 博客访问: 803093
  • 博文数量: 869
  • 博客积分: 201
  • 博客等级: 入伍新兵
  • 技术积分: 3376
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 19:42
文章分类

全部博文(869)

文章存档

2014年(4)

2013年(415)

2012年(453)

我的朋友

分类:

2012-10-13 11:09:05

原文地址:(二)、  点亮LED 作者:machoe

我个人是自学的嵌入式,在学校里老师详细教了单片机,又教了些嵌入式的一些“粗浅”功夫,工作后,也没有参加过系统的培训,回想当初自学的日子,那叫一个“苦、累”。现在再去总结,总感觉自己走进了误区,绕了很大一个弯。在此,我把自已的想法和大家分享一下,希望对后来人有所帮助。

嵌入式是一行涉及范围很广的行业,对于其硬件的体系结构、汇编与C编程语言、操作系统的使用和认识,一直到最后的Bootloader和内核移植、驱动、应用程序开发,每一个环节都涉及很多的知识,如果想把每一个环节吃透、消化掉,没有个35个月,恐怕也是不可能的。而初学者所容易走的也只是两条路:一条路就是拿来一本厚厚的书就从头到尾通读,读完一本又一本,结果没记住什么,拿来板子不会烧程序更不会编程序;另一条路就是买了开发板就从例程开始,拿来代码就编译下载,有了实验现象就乐不思蜀了,再回来看代码也不能好好斟酌,得过且过,这就导致了,只能看懂别人的代码,没有自己的东西。

鉴于以上两点,我在后面的学习心得中,我会结合知识和代码,只重点讲解和例程有关的知识点,后面会告诉大家去读哪些有用的文章和书籍,但这里,我建议读者重点看我讲的知识点,不要拿来一本书就一下子看完,把所有的东西全记住,“一口是吃不成胖子”的,随着本套博客系统的推出,当我们完成了本阶段的学习后,我想我们已经积累了很多的知识点,再回过头来看一些大作,如:《ARM体系结构与编程》也不会那么吃力了,我当时初学时,就通读了这篇大作,说实话,当时只理解了不到20%,现在再回头看看,感觉理解的要深得多了。

最后,由于我们是在LINUX环境下进行开发的,建议对不了解LINUX操作系统的朋友找一本书来看看,建议也不要通读,用一点,学一点,学一点,用一点,慢慢积累,这样等经过一段时间的学习,也就能慢慢掌握了。 

一、简述“程序的运行”

提到“程序”,大家首先想到的是肯定是我们自己所书写的一行行代码,如C代码、汇编代码。然而,我们仅仅知道这些还是不够的。相信现在学习嵌入式的朋友们,肯定多多少少有一些计算机、单片机的基础知识,计算机(我们常说的INTELAMDCPU)也好,单片机(如8051)也好,他们可不认识我们所写的“代码”,这就像我们和一个不懂“汉语”的外国人说中文一样,他根本不会理解你说的是什么。

CPU所能认识的只是二进制的机器码,通常以.bin结尾,而我们所书写的代码(以C语言为例)被我们称为源文件,通常以.c结尾。这时,就有一个问题摆在我们面前了。在现实生活中,如果遇到外国人,我们可以请一个翻译将我们讲的中文翻译成外语,这样就达到了沟通的目的,而在嵌入式这个特殊领域里,我们也可以找一个“翻译”,它就是----编译器。

编译器的工作就像翻译一样,将我们写的源文件:C代码和汇编代码翻译成CPU所认识的二进制文件,这样CPU就可以执行我们的指令了。注意:在我们现在所用到的编译器通常指预编译器、编译器、汇编器、链接器和反汇编器这些工具的总和,这些工具各自起到不同的作用,在后续的文章中,会一一讲解。这里读者需要理解可执行程序的形成过程:

 

上图是孙鑫老师的C++课程中课件截图,C++程序和我们现在学习的C程序编译的过程原理是一样的,请大家深入理解。

二、LINUX下的编程基础 1LINUX下的编译器

相信从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页。

A. arm-linux-gcc

这里只简单介绍该命令的使用方法,详细资料可详读参考资料中的《嵌入式LINUX应用开发完全手册》第3章。

-c  对源文件进行预处理、编译、汇编,但不做链接,生成中间OBJ文件,通常以.o结尾。

-g    添加调试信息

-o  指定输出文件。如果不指定-o filename 选项,默认输出为a.out文件。

B.  arm-linux-ld

-Ttext     startaddr

-Tdada    startaddr

-Tbss      startaddr

其中-T选项用来指定代码段、数据段、BSS段的起始地址。此外,还可以用来指定的链接脚本。本章中不涉及链接脚本,后续会详述。

知识点:

    可执行程序是由代码段、数据段、BSS段组成的。

    数据段:存放的是初始化的全局变量和静态变量。

    BSS段:存放的是未初始化的全局变量和静态变量。

 

 

 

 


C arm-linux-objcopy

用于将一个目标文件复制到另一个文件内,可以使用不同于源文件的格式输出到目的文件。常用于格式转化。

-O    用于指定输出的文件格式。如二进制 –O binary

-I   用于指定源文件的格式

-S  不从源文件中复制重定位信息和符号信息到目标文件

D. arm-linux-objdump

用于显示二进制文件住处。常用于进行反汇编,方便调试。

-D  反汇编所有段

-m  指定反汇编目标文件所使用的架构,如 –m arm 指定为ARM体系架构。

-b    指定输入文件的格式,这不是必须的,arm-linux-objdump能自动识别多种格式。

2. Makefile

关于Makfile要介绍的实在是太多了,这里仅简单进行说明,请大家参考《GNU makefile 手册》。

目标(target……. : 信赖(prerequiries

                                           :命令(command)

  这里需要注意的是命令前面一定要使用TAB键,不能用空格。请参照后面的实例进行学习,看手册不要看得太多,要边学边用,这样才会达到最好的效果。

三、点亮LED 1.硬件介绍

TQ2440开发板使用的是S3C2440 CPU,请大家学习本章的同时,参看S3C2440手册。

S3C2440130复用I/O口。从GPA~~GPJ,其中需要注意的是没有GPI端口。这些端口和单片机的P0~P3口十分相似,初学者可以完成“当成”是单片机的IO口来操作。

为了点亮我们开发板的LED,我们参考一下天嵌开板的原理图。

上述原理图分别取自于核心板原理图和扩展板原理图。上图表明,4LED连接在CPUGPB5678端口,而且是共阳的连接方式,如果要使其点亮,我们应该在这些端口中输出“0”。

2.GPIO寄存器简介

请大家参看手册。

GPIO引脚是通过寄存器来操纵的,由于GPIO引脚大部分都是复用功能,除了通用的I/O端口外,还有其它的功能,在上图中可以看出,GPB5还有一个名称叫“nXBACK”,因此,我们需要一个寄存器来选择它是通用的I/O功能还是额外的功能,这个寄存器就叫GPBCON

除了GPBCONGPB端口还有两个寄存器:GPBDATGPBUPGPBDAT用于确定引脚的电平状态,当读操作时,读该寄存器就可以知道引脚是高电平或低电平;当写操作时,向寄存器中写01 ,就可以操纵引脚了。

三个寄存器的地址:

GPBCON   0x56000010

GPBDAT    0x56000014

GPBUP     0x56000018

3.实例分析

下面列举出的是韦东山老师的代码:

@******************************************************************************

@ Fileled_on.S

@ 功能:LED点灯程序,点亮LED1

@******************************************************************************      

.text                                    @定义一个代码段

.global _start               @定义一个全局入口

_start:                    @全局入口处

            LDR     R0,=0x56000010       @ R0设为GPBCON寄存器。此寄存器

                                                                @ 用于选择端口B各引脚的功能:

                                                                @ 是输出、是输入、还是其他

            MOV     R1,#0x00000400       

            STR     R1,[R0]                          @ 设置GPB5为输出口, [10:9]=0b01

            LDR     R0,=0x56000014       @ R0设为GPBDAT寄存器。此寄存器

                                                                @ 用于读/写端口B各引脚的数据

            MOV     R1,#0x00000000    @ 此值改为0x00000020,

                                                                @ 可让LED1熄灭

            STR     R1,[R0]                          @ GPB5输出0LED1点亮

MAIN_LOOP:

            B       MAIN_LOOP

 

 除了韦东山老师的注释,我又增加了一些,如果看这段程序还吃力的同学,请查阅《ARM体系结构与编程》中的相关章节,请注意,只要看懂上述代码即可,不求将所有的指令全掌握。

上述代码只是源文件,我们还需将其编译成可执行的.BIN文件,请看下面的Makefile文件。 


led_on.bin : led_on.S                                                                              #led_on.S源文件生成led_on.bin文件

         arm-linux-gcc -g -c -o led_on.o led_on.S        #将源文件编译,但不链接,生成led_on.o中间文件

         arm-linux-ld -Ttext 0x0000000 -g led_on.o -o led_on_elf    #将中间文件链接成起始地址为0x0000000.elf文件

         arm-linux-objcopy -O binary -S led_on_elf led_on.bin           #.elf可执行文件的格式转化成.BIN格式

         cp  led_on.bin /opt/machoe/tftpboot –f                                    #将生成的.BIN文件复制到TFTP目录下,见第一章。

clean:

         rm -f   led_on.bin led_on_elf *.o

 

在文章发表后,我会将源代码打包,放到网上,网址稍后会公布出来。

在该文件夹下,点击make,可以看到下图:

上图表明,我们已经成功编译,下面就烧录到开发板中,验证一下我们的实验结果。

具体的操纵方法如下(详见第一章):

1.       打开MINICOM

2.       启动开发板,从NOR FLASH启动。

3.       q退出BOOTLOADER

4.       使用如下命令烧写并执行程序,见下图:

这时我们会在开发板中看到,第一个LED被点亮。

请大家熟悉操纵流程,并试着自己改一下代码,点亮两个LED。以上部分所涉及的知识点较多,希望大家不要满足,多参考其它资料以充实。

四、参考资料与推荐阅读

1.韦东山 《嵌入式LINUX应用开发完全手册》 第235

2.杜春雷  ARM体系结构与编程》    指令介绍章节

3.三星公司 《S3C2440手册》       指令介绍章节和第9

4.GNU GCC手册》

5.GNU Makefile 手册》

 

阅读(152) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~