第二季-专题1-工欲善其事-必先利其器

专题1-工欲善其事-必先利其器

第1课-裸机开发快速体验

早期的嵌入式系统是基于windows系统的,使用ADS和RVDS进行相关的操作,一些重要的操作都是完成的。在使用win7 64位系统的时候,又常常出现兼容性的问题。在本次课程当中,我们所有的开发都是基于linux平台来进行的。我们将自己完成makefile的编写,lds(连接器脚本)的编写,以及文件的调试eclipse的使用。

本课程的学习目的是学习裸机开发的流程和使用的工具。

流程:

  1. 编写裸机程序。
  2. 调试裸机程序。
  3. 生成2进制映像文件(编译、链接、格式转换)。
  4. 烧写运行2进制文件。

本次课程只进行第三步和第四部。

具体操作:

  1. 为了方便后面课程的学习,我们要在home目录下创建新的文件,以用于本次课程的学习和存储。这里要注意由于我们刚开始进入的是随便的一个用户的操作界面,并不具有完全的权限,我们要通过输入 su - root来进入管理员操作界面。rm 指令用来删除文件,rm -r用来删除文件夹。
  2. 当使用smb服务器是有的时候会有访问权限有限制的时候,这时我们需要改变文件的权限。原因是我们新建的文件夹只是具有读取的权限不具有访问的权限。我们只需要输入命令:chmod 777 -R ./即可。

在主界面输入:

ls   /  显示在虚拟机我的电脑中的文件

cd  /  进入我的电脑的文件夹

cd  /home 进入home文件夹,创建我们需要的文件夹和文件

mkdir S3-ARM用来建立新的文档,储存本次用来操作的程序

mkdir part1建立新的文件夹

mkdir lesson1   pwd,之后进入我们指定的文件之中。

文件的建立结束,下面开始在该文件下运行/etc/init.d/smb restart  ,刚开始运行这段程序的时候显示,无法找到该文件,这里的问题出现在前期嵌入式积累下来的问题。解决方法就是将转载光盘挂载,重新安装smb服务器。

操作步骤:

我们利用smb服务器导入ARM-tools.tar.gz文件。通过命令:tar xvzf ARM-tools.tar.gz解压文件。

进入解压后的文件夹,找到文件arm-linux-gcc-4.3.2.tgz.有些人若是安装了这一个文件,想要删除的话,需要命令: rm /usr/local/arm -rf

解压:tar xvzf arm-linux-gcc-.4.3.2.tgz -C /

这里进行相关的tar操作的说明。

-c创建.tar格式的文件

-x解开.tar格式的文件

-f使用归档文件

-v显示详细信息

-t查看包内文件

-j使用baip2程序

-z使用gzip程序

-p打包时保留文件及目录的权限

-P打包时暴力会文件及目录的绝对路径

-C释放的目的地,指定的解压位置。

这里注明,我们将文件解压后会放在usr/local/arm中,在bin文件夹中,有着我们要用的工具链(工具链就是很多的工具的文件的集合)

我们将文件放在了指定的文件夹中,按理说我们就只能在这个文件中使用这个文件。为了我们可以在其他文件夹中直接使用,不需指明路径,我们可以修改:vim /root/.bashrc

在这个文件里面加入修改:export PATH=$PATH:/usr/local/arm/4.3.2/bin/一个不能换。

通过输入source  /root/.bashrc使文件生效

  1. 下面把提供到的裸机程序,变成二进制镜像。

先把裸机程序复制到linux系统中。有两个文件:led.lds和led.S,我们看到的文件led.S就是事先编写好的汇编程序,我们将它变成二进制印象文件。输入命令:arm-linux-gcc -g -c led.S 产生文件led.o。(编译)

输入命令arm-linux-ld -Tled.lds -o led.elf led.o (链接)生成led.elf文件,叫做链接器脚本。

下面将文件led.elf进行格式转换:arm-linux-objcopy -O binary led.elf led.bin

这时我们得到了我们要的led.bin文件,这就是我们要烧录的文件。

我们要生成我们要的二进制文件,进行了以上的三步。为了简洁我们可以用makefile来完成上述的操作 。

我们输入:make clean将上面操作的文件全部删除。在键入:make我们之前的操作就全有了。这里我们就用到了makefile这个文件。

  1. 烧写文件

开发板上类似于硬盘的部分是nand flash,我们写的程序以及最终安装的系统,最终都是希望在nand flash上运行的。2440的开发板有一个nor flash,6410和210没有nor flash,但是有SD卡。希望将程序安装在nand flash我,我们都是借助在SD卡或者nor flash里面安装的系统辅助程序来完成的。我们在nor flash或者SD上与电脑建立一个连接,将程序下载到这上面,在给nand flasf

这里注意,我们用的裸机开发usb驱动,即dnw_usb.ko这个文件有我们之前烧录系统时用的驱动是不一样的。我们要把之前的驱动卸载了rmmod dnw_usb.ko。然后导入新的文件重新安装(在哪个文件夹下面运行就执行哪个文件夹下面的命令):insmod dnw_usb.ko。

连接TQ210的串口线与USB下载线,设置开发板从SD卡启动,启动SecureCRT。我们先将输入9,格式化nand flash,在输入1。

安装好了驱动之后我们先导入210的头文件,为以前编辑好的文件加头, 将led.bin这个文件重新产生其他的文件。

./mkv210  led.bin  led-210.bin

生成的led-210.bin就是我们要倒入TQ210中的文件。

在linux系统中输入./dnw led-210.bin 0x20000000  这样我们就已经把文件烧录到了开发版之中。

断电,从nand flash重新启动,我们就能看见拨钮旁边的两个led灯亮了,说明我们上面的操作是正确的。

第2课-交叉工具链

 

         本课所介绍的文件,具体是什么功能的,主要看工具的末尾是什么;看在什么平台上使用,主要看工具的开头是什么。

  1. 什么是交叉工具链

链,表示集合的意思,交叉工具链是一个集合,不是一个工具,是多个交叉工具。

嵌入式开发模型—交叉开发

在嵌入式开发的过程中有宿主机和目标机的角色之分:宿主机是执行编译、链接嵌入式软件的计算机;目标机是运行嵌入式软件的硬件平台。这种模式叫做交叉开发模式。

  1. 常用的交叉工具

交叉编译器,交叉链接器,交叉转换器,交叉ELF文件工具,交叉反汇编器

(1)交叉编译器arm-linux-gcc 例如:arm-linux-gcc hello.c [option] hello

arm-linux-gcc hello.c -o hello       arm-linux-gcc -static hello.c –o hello

他和gcc之间有一定的差别,主要是头文件的位置不同。

我们在pc机上编写一个文件hello,使用静态的方式gcc -static hello.c –o hello,将文件导入优盘,将优盘插入我们烧写好的开发板中,开发板会自动识别优盘,使用命令cd /udisk 运行./hello,发现运行不了。但是使用交叉编译链编译的文件是可以运行的。

使用file -hello,查看文件的属性,可以看到使用gcc编译的属性是Intel 80386,使用arm-linux-gcc编译的属性是ARM

gcc自动从/usr/include/下寻找标准头文件,使用命令arm-linux-gcc --help,显示arm-linux-gcc的信息,找到-print-search-dirs参数,输入arm-linux-gcc -print-search-dirs,显示了arm-linux-gcc从哪里寻找的头文件。

(2)交叉链接器arm-linux-ld   例如:arm-linux-ld -Tled.lds -o led.elf led.o 

使用命令arm-linux-gcc –g –c les.S 其中-c表示只编译不链接

         使用命令arm-linux-ld -Tled.lds -o led.elf led.o其中-T表示使用连接器脚本led.lds,生成文件led.elf,是将中间文件led.o进行的链接。运行完这段程序后生成文件led.elf,elf格式的文件。

(3)elf文件工具arm-linux-readelf  

例如:arm-linux-readelf -a led.elf    -a表示全部的意思,即显示文件头,得到有用的信息,例如可以看到文件的大小端。我们编译的程序在小端的模式运行。

我们编辑的应用文件,如果没有办法在arm平台运行,可以使用file命令,查看文件运行平台是否正确,也可以利用上面的办法查看大小端是否正确,以及下面的命令查看是否库文件具备。

arm-linux-readelf -d led.elf       -d表示显示我们需要的文件库。若是开发板上没有我们需要的文件库,将无法运行该文件。

(4)交叉反汇编器arm-linux-objdump例如:arm-linux-objdump -D -S hello >dump

         使用命令arm-linux-gcc hello.c -o hello,生成hello文件,使用命令file hello查看该文件的格式,发现是elf格式得到,在ARM平台下运行。现在对于他反汇编。

使用:arm-linux-objdump -D -S hello >dump

>dump表示输出到dump这个文件里面。

为了使我们得到的汇编程序有更好的可读性,我们可以执行下面的操作:

arm-linux-gcc -g hello.c -o hello再进行反汇编arm-linux-objdump -D -S hello >dump

其中-g的作用是,附加调试信息。这样我们在main函数中我们就能看见c语句和汇编语句的对应关系。

(5)文件格式转换器arm-linux-objcopy。

我们之前所有的操作的文件都是elf格式的文件,但是这个文件是没有办法在开发板中运行的,所以我们需要这个程序将它的格式转换。我们要将elf格式的文件转换成bin格式的文件。

我们之前操作的hello就是elf文件,之所以能在开发板生运行,是因为开发板是linux系统,自带elf解析器,可以将elf文件当做二进制文件进行运行。

例如:arm-linux-objcopy -O binary led.elf led.bin

-O表示输出文件的格式,binary表示文件的格式是二进制;led.elf是输入文件led.bin是输出文件。

第3课-Makefile工程管理

 

一.为什么用Makefile

使gun make工具来管理程序是每一个linux工程师都必须掌握的技能。Make能够使整个程序进行编译、链接只需要一个make命令就可以了。

Make的工作主要依赖于一个叫做makefile的文件。该文件放在操作目标的文件夹里。Makefile文件描述了整个程序的编译、链接等规则。其中包括:工程中的那些文件需要编译以及如何编译,如何最后产生我们要的可执行文件。我们对使用的Makefile进行截图操作:

 

二.Makefile的构成

  1. 构成

Makefile中最重要的组成部分就是“规则”

规则:用于说明如何产生目标文件,规则的格式如下:
target: prerequisites        

command

目标:依赖    

命令

这里强调,command(命令)前面要用【TAB】键空格。

例如:

led.elf: led.o

arm-linux-ld - Tled.lds -o led.elf led.o

该命令的作用是生成目标文件led.elf,它的依赖文件是led.o,具体的一系列操作是arm-linux-ld - Tled.lds -o led.elf led.o

  1. 伪目标

这里首先举例我们Makefile文件中的内容:

all:led.o

arm-linux-ld -Tled.lds -o led.elf led.o

arm-linux-objcopy –O binary led.elf led.bin

led.o : led.S

arm-linux-gcc -g -o led.o -c led.S

.PHONY: clean

clean:

rm *.o led.elf led.bin

一条规则的依赖和命令可以有多个,但是目标就只能有一个。

在上述的规则中,clean中只有命令,没有依赖,这称为伪目标。伪目标前面有关键字.PHONY: 提醒读者这就是伪目标。

  1. 最终目标

当一个Makefile中有多条规则时,如何单独的执行某一条规则。如果用户没有指定执行某一条规则,make会默认执行makefile中的第一条规则,而这条规则就称为:最终目标。

例如,上述Makefile中有三个目标,我们如果要生成led.o,直接输入make led.o就可以。如果只是输入make,就会默认生成第一条指令,由于本指令的特殊结构,会依次运行

arm-linux-gcc -g -o led.o -c led.S

arm-linux-ld -Tled.lds -o led.elf led.o

arm-linux-objcopy -O- binary led.elf led.bin

这三条指令。具体内容自行分析。

  1. makefile的规则-变量

使用变量前:

app1:aap1.o func1.o func2.o

gcc app1.o func1.o func2.o -o app1

app2:aap2.o func1.o func2.o

gcc app2.o func1.o func2.o -o app2

使用变量后:

obj=func1.o func2.o   # 变量的赋值,在Makefile中变量是没有种类区分的,而且在“=”两边是没有空格的

app1:aap1.o $(obj)

gcc app1.o $(obj) -o app1

app2:aap2.o $(obj)

gcc app2.o $(obj) -o app2

通过变量的赋值达到了程序简化的作用。在makefile中“#”字符后面的内容视为注释

在Makefile中,用户除了可以自己定义变量外,还可以使用存在系统已经定义好的默认变量。

$^:代表所依赖的文件

$@:代表目标

$<:代表第一个依赖的文件

使用前:

led.o: led.S

arm-linux-gcc -g -o led.o -c led.S

使用后:

led.o: led.S

arm-linux-gcc -g -o $@ -c $^

现在我们用该方式,将我们例程makefile中的文件更如下:

all:led.o

arm-linux-ld -Tled.lds -o led.elf $^

arm-linux-objcopy -O- binary led.elf led.bin

led.o : led.S

arm-linux-gcc -g -o $@ -c $^

.PHONY: clean

clean:

rm *.o led.elf led.bin

经过如此变动,Makefile功能不变。

  1. Makefile构成-通用规则

当makefile文件中有许多类似的规则的时候,将这些规则合并成为一条通用的规则。

例如在一个大的工程文件中,有如下的Makefile文件:

led.o : led.S

arm-linux-gcc -g -o $@ -c $^

main.o:mian.S

arm-linux-gcc -g -o $@ -c $^

run.o:run.S

arm-linux-gcc -g -o $@ -c $^

lee.o:lee.S

arm-linux-gcc -g -o $@ -c $^

文件中有好多类似的规则,我们可以将这些规则合并到一起,该为下列的程序:

%.o : %.S

arm-linux-gcc -g -o $@ -c $^

完成了多条语句的合并。

三.Makefile使用技巧

  1. 去回显

回显:在执行一步Makefile时往往会显示出来执行该命令的命令语句,这便是回显。

当我们执行make clean的时候,会显示rm *.o led.elf led.bin,同样我们执行make led.o会显示arm-linux-gcc -g -o led.o -c led.S,这就是回显

由于回显也是占用一定是时间的,所以在执行大的命令的时候我们是要把回显消除的,以求得节省时间。

具体的做法事,只要在Makefile文件要消除回显的部分加上@就好。例如:

hello: hello.c

@gcc hello.c -o hello

  1. 修改makefile文件名

make命令默认在当前目录下寻找名字为makefile后者Makefile的工程文件,当名字不为这二者之一的时候,可以使用如下方法指定:

make -f 文件名

例如:先执行mv  makefile  file

我们现将makefile命名为file,我们在执行make时便不能运行,这时候我们只要运行 make -f file就可以了。

第4课-链接器脚本

连接器脚本不仅在裸机课程中有作用,更在后面内核学习中也有很大的作用。

 

一.连接器脚本的神奇作用

例如在上文点亮led灯的实验中,我们中有main.c函数和start.s文件,其中main.c函数包含在start.S文件中,通过bl  mian.c进行调用。

这里我们可以将./dnw ./led.bin 30000000运行,将文件烧写到板子中。分别使用led1.lds和led2.lds两个链接器脚本,并不对程序进行任何修改,会发现在板子上观察的效果不同。

二.脚本的构成

  1. 基本构成-段

一个可执行的程序包括:代码段(放代码),数据段(放初始化的全局变量),bss段构成(放没初始化的全局变量)。同样,在用于链接这个程序的连接器脚本中,就会反应出这几个段的信息。连接器脚本的后缀是.lds

这里我们创建一个连接器脚本。

vim  led.lds开创文件

SECTION{

.text :      代码段(注意空格  )

{

*(.text)   表示所有文件的代码

}

.data :       数据段

{

*(.data)     表示所有文件的数据    

}

.bss :

{

*(.bss)      所有文件的bss段

}

}

通过 vim makefile更改makefile中的文件,将led2改为led。

2. 设置起始链接地址

vi  led.lds

更改

SECTION{

. = 0x30000000;     //起始的地址,可根据反汇编来查看,以后会讲解

. = ALIGN(4);         当前地址,   ‘.’表示当前地址

.text :              代码段

{

start.o(.text)      首先运行start.o

*(.text)           表示所有文件的代码

}

. = ALIGN(4);

.data:              数据段

{

*(.data)            表示所有文件的数据    

}

. = ALIGN(4);

bss_start = .; //将bss_start = 赋当前地址

.bss:

{

*(.bss)      所有文件的bss段

}

. = ALIGN(4);

bss_end =.;

}

  1. 对齐设置

能整除4的地址叫做四字节对齐地址,在存储数据是我们一般希望能够将他们放在能整除4的对齐地址上,这使得在访问时能有更好的效率。

. = ALIGN(4);表示在当前初始地址的基础上,将地址进行四字节对齐,在哪个段加入这条指令表示对于哪个数据或者代码进行四字节对齐。如上面的更改。

  1. 变量

为了方便应用我们在链接器脚本中同样引入变量。

bss_start = .;和bss_end =.;分别记录bss段的开始和结束的地后面的地址,在后面的操作中可以应用得到。

  1. 设置代码段首文件

在运行连接器脚本中,首先执行的文件是十分重要的,后面的2、3、4号文件就显得一般了。因为首先运行的文件中往往要包含一些初始化的文件。例子中先运行start.o文件。

这里我们明白我们当时对比的led1.lds(先运行start.o,完成CPU的初始化)和led2.lds(先运行main.c,没有完成CPU的初始化)的区别,因为后者并没有先运行初始化文件,所以是点亮不了灯的。

第5课-Eclipse集成开发环境

         在逻辑程序开发的过程中,我们编写的程序并不一定就是完全正确的,还需要我们对它进行改进,Eclipse集成开发环境可以支持在线的更改,同时它也支持程序编译的功能

         首先,我们先了解以下Eclipse的示意图,如下:

 

         需要的硬件主要有开发板和Jlink线,elipse和GDB Server通信完成对开发板的间接控制,需要安装的软件主要有:sdb server、jlink和eclipse这三个软件。

准备工作:

  1. 从SD/nor flash启动,格式化nand flash
  2. Jlink连接、串口连接、nand flash(1000)启动

 

 安装工作:

  1. 安装gdb server

找到给定的压缩包ARM-Tools.tar,使用smb服务器将它放到我们的linux操作目录下。

使用命令tar xvzf ARM-Tools.tar.gz解压压缩包,进入子目录如下:

使用命令tar xvzf arm-linux-gdb-7.5.tar.gz解压gdb包,子目录如下:

使用命令./build-all,对该文件进行编译与安装,整个过程大概持续5分钟。

我们需要添加路径,实际上build-all就是安装的脚本文件,里面记录了安装的位置,具体在/opt/arm-linux-gdb/bin目录下。

使用命令vim /root/.bashrc,在里面添加命令export PATH=$PATH:/opt/arm-linux-gdb/bin/

这条指令要加载在我们之前设置的交叉编译链之前,因为以前安装的交叉编译链之中也是有gdb的。

         当我们使用命令arm-linux-gdb时,会发现还是以前的版本,不是我们安装的版本,重新注销系统在登录就可以了。

 

  1. 安装Jlink文件

解压tar xvzf Jlink_Linux_V434a.tgz,进入子目录,如下:

复制库文件

在开发板连接正确而定情况下,运行./JlinkGDServer,就会显示连接的开发板的内核版本。

  1. 安装eclipse

(1)安装

正常的系统中是自带eclipse的,但是由于版本过低不能使用。

使用命令which eclipse,显示eclipse的安装位置

         进入这个位置,将使用命令mv eclipse eclipse-back,将eclipse隐藏。

         在安装包软件中输入tar xvzf eclipse-cpp-helios-SR2-linux-gtk-.tar.gz

         进入子目录启动./eclipse,可以将文件的放在./root/home/work/s2/p1/Jlink目录下,第一次启动该程序会出错,不用在意,在启动一次就好。到这里,我们完成了eclipse的安装。

(2)设置

         在开始调试之前确保虚拟机是可以正常上网的。

         运行./eclipse启动软件,在help选项上选择install New Software安装必要的插件如下:

 

         在出现的菜单里面输入网址,进行文件添加,如下:

 

       选择next-accept-finish完成插件安装,重现启动使配置生效。长时间卡在calculating requirements and dependencies ,把“Contact all update sites during install to find required software”(寻找指定的软件前先访问所有更新站点)前面的勾去掉,然后f返回重新安装,这样之后问题迎刃而解。

(3)使用

 

         在file选项中选择new,接着选择Makefile Project with Exiting Code,找到我们之前使用额文件,创建项目名字为led:

 

         点击finish完成创建,如下:

 

         在project选项中,把Build Automatically去掉,先将所有的编译生产项去掉,点击右键选择Clean Project。在选择Project选项,选择build all。实际这一个操作就是运行文件中带的Makefile文件,得到我们的led.bin文件。

         选择led.bin文件,找到像个小虫子的debug的选项,选择Debug Configurations,双击最下面的选项,出现led Default,输入调试文件的位置,我们调试的是led.elf文件,如下:

 

         设置Debugger栏如下:

 

         在Commands栏目,导入初始化的文件,将初始化文件,导入linux系统,利用命令

gedit init-210打开文件,复制其中的内容,粘贴到命令栏。init-210的内容如下:

# connect to the J-Link gdb server

target remote localhost:2331

# Set JTAG speed to 30 kHz

monitor endian little

monitor speed 30

# Reset the target

monitor reset

monitor sleep 10

 

# Setup GDB for faster downloads

#set remote memory-write-packet-size 1024

monitor speed auto

break main

load

 

(4)调试

猜你喜欢

转载自www.cnblogs.com/free-1122/p/11451970.html