《嵌入式系统实验》指导书计科.docx
《《嵌入式系统实验》指导书计科.docx》由会员分享,可在线阅读,更多相关《《嵌入式系统实验》指导书计科.docx(36页珍藏版)》请在冰豆网上搜索。
《嵌入式系统实验》指导书计科
《嵌入式系统实验》指导书
目录
实验一Linux操作系统安装及常用命令使用
实验二嵌入式Linux下C语言编程
实验三嵌入式Linux多任务应用程序设计
实验四嵌入式Linux设备驱动程序设计
实验五ARM开发环境实验
实验六ARM汇编语言编程
实验一Linux操作系统安装及常用命令使用
一、实验目的
1.熟悉Linux操作系统的安装;
2.掌握Linux中的常用命令;
3.掌握vi编辑器的基本用法;
二、实验设备
1.硬件:
PC机Pentium500以上,硬盘10G以上;
2.软件:
PC机操作系统,VMware-workstation-5或以上版本,LinuxReadHat操作系统安装包。
三、实验原理
根据Linux系统在计算机中的存在方式,将Linux的安装分为单系统、多系统和虚拟机。
本实验采用的是虚拟机安装方式,即在已经安装好的Windows系统下,通过虚拟机软件虚拟出供Linux安装和运行的环境。
Linux文件系统具有良好的结构,系统提供了很多文件处理程序。
这里主要介绍常用的文件处理命令。
1.cd:
访问Linux文件系统目录。
格式:
cd目录名
2.mkdir:
建立名称为dirname的子目录。
格式:
mkdir[options]目录名
3.rm:
删除文件或目录。
格式:
rm[options]文件或目录
4.mv:
为文件或目录改名,或者将文件由一个目录移入另一个目录中。
格式:
mv[options]源文件或目录目标文件或目录
6.ls:
用于显示目录内容。
格式:
ls[options][filename]
vi编辑器是RedHat系统的缺省文本编辑器。
vi编辑器是一种功能强大、应用广泛的编辑工具。
它的基本操作方法如下:
1.启动vi编辑器
在提示符后输入以下命令,启动vi:
$vifilename
2.输入文本:
i在光标之前输入文本。
光标后的所有内容都向右移。
3.保存工作并退出vi
无论是否退出vi,均可保存所做的工作。
按ESC键,确定vi是否处于命令模式。
:
w保存,但不退出vi
:
wq保存并退出vi
四、实验步骤
1.在虚拟机VMware下安装Linux操作系统
(1)配置虚拟机
鼠标左键单击桌面上的VMwareWorkstation图标,启动虚拟机软件,鼠标左键单击“NewVirtualMachine”图标,创建一个新的虚拟机。
接着单击“下一步”按钮,出现选择虚拟机类型时,选择“Typical”(典型)类型。
出现选择要安装的操作系统时,选择“Linux”选项,然后在“Version”下拉列表框中选择“RedHatLinux”选项。
接下来就是虚拟机的网络配置,选择默认选项“Usebridgednetworking”,系统会自动为虚拟机的网络连接建立虚拟网卡,使得虚拟机拥有独立IP地址,对外进行网络连接。
最后,需要给虚拟机分配硬盘空间大小,根据安装需要输入相应的数字。
此处选择默认的8GB并且选中复选框“Allocatealldiskspacenow”,接下来,需要等待较长的一段时间给虚拟机分配磁盘空间,磁盘空间分配完毕后,虚拟机就创建好了。
此时会在虚拟机文件夹下生成一个8GB的文件和一些其它文件。
选择菜单项“VM/Settings…”进入虚拟机设置界面,单击“Add…”按钮,进入添加硬件导航界面,选择“SerialPort”项后单击“Next>”按钮,然后接受默认选项“Usephysicalserialportonthehost”,表示使用主机中的物理串口,然后单击“Next>”按钮,在物理串口选择界面中选择“Autodetect”,表示自动选择,然后单击“Finish”按钮完成串口的添加。
(2)在虚拟机上安装Linux
在虚拟机上安装Linux了,有光盘和光盘镜像文件两种安装方式。
这里采用第二种方式。
使用光盘镜像文件安装方式时,需要设置虚拟机的光驱连接方式为“UseISOimage”。
具体设置步骤为:
选择菜单项“VM/Setting…”,进入虚拟机设置界面,选择窗口左边的“CD-ROM”项,在窗口右边选择“UseISOimage”项,然后选择单击“Browse”按钮,将Linux第一张安装光盘的镜像文件连接到虚拟机光驱上,选择菜单“Vm/Power/Poweron”启动Linux虚拟机,可以看到Linux虚拟机开始启动。
1)选择安装方式
虚拟机启动后进入到Linux安装方式选择界面,直接按回车键选择以图形界面安装;输入“linuxtext”字符串后再按回车键以字符界面安装,按功能键F1~F5显示进一步的详细信息。
此处直接按回车键选择以图形界面安装。
2)测试光盘
接下来进入测试光盘界面,此时按键盘上的方向键可在“Skip”和“OK”之间来回选择,当选择“Skip”并回车时,表示不测试光盘而直接进行安装;当选择“OK”并回车时,表示需要先测试光盘是否正确无误,以避免安装过程中由于光盘的错误而导致安装失败。
此处使用光盘镜像文件安装,因此,选择“Skip”后回车,不对光盘进行检测。
3)以图形界面开始安装
接下来进入图形安装界面,鼠标单击“Next”按钮进入下一个安装界面继续安装,单击“Exit”按钮放弃安装。
此处用鼠标单击“Next”按钮进入下一个安装界面继续安装。
4)语言选择
接下来进入语言选择界面,共有“简体中文”、“繁体中文”、“英文”、“日文”、“韩文”等五种语言,默认为英文。
此处选择“简体中文”,然后用鼠标单击“Next”按钮进入下一个安装界面继续安装。
5)是否接受安装协议
接下来进入是否接受安装协议选择界面,选择“接受”可继续安装过程,选择“不接受”放弃安装,默认选择为“不接受”。
此处选择“接受”,然后用鼠标单击“Next”按钮进入下一个安装界面继续安装。
6)选择键盘
接下来进入键盘选择界面,可以选择“日语键盘”或“英语键盘”,默认选择“英语键盘”。
此处选择“英语键盘”,然后用鼠标单击“Next”按钮进入下一个安装界面继续安装。
7)磁盘分区设置
接下来进入磁盘分区设置界面,如果要安装Linux的磁盘是一个未初始化的新磁盘或磁盘的分区格式未知时,会弹出磁盘初始化的警告界面,提示用户必须要对其先进行初始化,并且初始化会删除原来磁盘中的所有数据,如果选择“是(Y)”,对磁盘进行初始化,如果选择“否(N)”,放弃安装。
8)网络与主机名设置
接下来进入网络与主机名设置界面,在“网络设备”栏中可以利用复选框选定引导时要激活的网卡,单击右边的“编辑(D)”按钮可以设定和编辑选定网卡的参数。
默认情况下,系统将在引导时自动激活主机中的网卡,并利用网络中的DHCP(DynamicHostConfigurationProtocol,动态主机配置协议)服务器获取网络参数。
在“主机名”栏中,可以接受默认选项“通过DHCP自动配置(a)”来自动获取主机名,或者选择“手工设置(m)”选项来为主机设置名字。
此处接受系统的默认选项,单击“下一步”按钮进入下一个安装界面。
9)时区设置
接下来进入时区设置界面,鼠标单击地图中的某个区域或者列表框都能够选择不同的时区,默认为“亚洲/北京”。
单击“调整日期和时间”按钮,会弹出修改当前主机时间的窗口,以修改当前的时间。
此处接受系统的默认选项,单击“下一步”按钮进入下一个安装界面。
10)设置root用户口令
接下来需要设置root用户口令,root用户是Linux系统中的管理员,拥有至高无上的权限,是系统在安装过程中自动创建的用户。
root用户的密码不少于6个字符,可以是大小写字母、数字以及键盘上其他字符的任意组合,由于在输入时密码不回显,因此要求输入两次,以避免输入过程中的失误。
11)设置安装软件包
12)开始安装
若所选择安装的软件包依赖关系校验未通过,需要回到上一步重新选择要安装的软件包,否则,单击“下一步”按钮会弹出安装过程中所需光盘的提示,单击“继续(C)”按钮开始安装,单击“上一步(B)”按钮回到设置安装的软件包界面,单击“重新引导(R)”按钮将放弃安装,重新引导系统。
此处单击“继续(C)”按钮开始安装软件包,系统将首先格式化分区,然后开始安装。
13)换盘操作
当前盘安装完成后,系统会提示插入下一张光盘以继续安装。
对于直接用光盘安装的方式,从光驱中取出原盘,放入下一张光盘,单击“确定”按钮继续安装。
对于利用光盘镜像文件安装的方式,需要同时按住键盘的Ctrl和Alt键释放鼠标,使鼠标能够移出虚拟机窗口,然后选择菜单“VM/Setting…”设置虚拟机,将下一张光盘的镜像文件连接到虚拟机的光驱上后,单击“确定”按钮,继续安装。
14)显示设置
安装结束之前,显示如图2-1所示的显示设置界面,对于虚拟机形式安装的Linux,此时不要修改系统默认的分辨率和色彩深度,因为还未安装VMwareTools,设置不会生效,对于单系统或多系统安装的Linux,此时可以设置系统分辨率和色彩深度。
2.练习Linux中的常用命令;
1)在RedHatLinux中创建一个普通账户jsj。
useraddjsj
2)进入/home/jsj目录下
cd/home/jsj
3)查看当前所在目录
pwd
4)在/home/jsj目录下创建一个文件test,在/home/jsj目录下创建一个文件夹folder,将文件test复制到folder目录下。
touchtest
mkdirfolder
cptestfolder
5)将/home/jsj目录下的文件test移动到/home/jsj/folder目录下。
mvtest/home/jsj/folder
6)删除/home/jsj目录下的folder文件夹。
rmfolder-r
7)进入/root目录下,查看所有文件(包括隐藏文件)。
ls-a
3.练习vi编辑器的基本用法。
1)在/home/jsj下用vi新建一个文件123。
vi123
2)在文件123中插入插入以下文字:
Hello,World!
3)保存文件并退出vi。
:
wq
五、思考题
如何实现Windows和虚拟机中的Linux进行文件共享?
实验二嵌入式Linux下C语言编程
一、实验目的
1.熟悉CVT-PXA270教学系统中的Linux开发环境;
2.掌握简单的Linux应用程序-helloworld的编译;
3.掌握CVT-PXA270教学系统中Linux应用程序的调试。
二、实验设备
1.硬件:
CVT-PXA270嵌入式实验箱、PC机Pentium500以上,硬盘10G以上;
2.软件:
PC机操作系统redhatlinux9.0+Linux开发环境。
三、实验原理
helloworld程序是一个只在输出控制台(计算机屏幕或者串口控制台)上打印出“Hello,World!
”(英语,意为“你好,世界!
”)字串的程序。
该程序通常是计算机程序设计语言的初学者所要学习编写的第一个程序。
它还可以用来确定该语言的编译器、程序开发环境以及运行环境已经正确安装。
本实验也将helloworld程序作为第一个学写的程序,并通过实际的动作让学生了解嵌入式Linux应用程序开发和PC机中Linux应用程序开发的异同。
1.交叉编译
本实验所使用的开发系统是x86体系结构的Linux系统(RedHat)。
而我们的目的是要开发能够运行在CVT-PXA270教学实验箱中的Linux应用程序。
由于CVT-PXA270教学实验箱中的Linux本身不具有自己的编译工具,因此我们必须在RedHat中进行交叉编译,编译完成后将执行码下载到CVT-PXA270教学实验箱中的Linux,然后运行或者调试。
这样做的另外一个好处是,在采用RedHat的主机系统通常其CPU速度、接口等软硬件资源都比CVT-PXA270教学实验箱中的Linux要丰富得多,因此在其上进行交叉编译效率要高得多。
在同一平台编译能够运行在不同平台上运行的程序的最主要差别在于所采用的编译器不同。
在Redhat中编译x86平台的程序采用gcc编译器,而编译ARM平台的程序采用arm-elf-gcc或者arm-linux-gcc编译器。
CVT-PXA270教学实验箱中,所有Linux实验均采用arm-linux-gcc编译器编译。
2.helloworld的编译
helloworld可以说是最简单的应用程序,通过如下命令进行编译:
$gcc-ohelloworldhelloworld.c
其中-o指定输出文件到helloworld,helloworld.c为编译的源文件。
该命令执行后,将对helloworld.c文件进行编译,并将生成helloworld可执行文件。
这个文件就是在指定平台上可以运行的执行程序,如果使用gcc进行编译即为可在x86平台上运行的程序,如果使用arm-linux-gcc进行编译则为可以在ARM平台上运行的程序。
3.Makefile文件
Makefile文件的作用有点类似于DOS下的批处理文件,通过编写Makefile文件,用户可以将一个很复杂的程序(可能包含上百个甚至更多的源文件或者目录)通过简单的make命令进行编译。
四、实验步骤
1.建立工作目录
注:
本实验以及后续的所有实验中用“$”符号表示在主机的Linux控制台上输入的命令行。
用“#”符号表示在目标机的Linux控制台上输入的命令行。
$cd/home/jsj
$mkdirhelloworld
$cdhelloworld
2.编写程序源代码
#include
intmain(){
printf("Hello,World!
\n");
}
3.在主机端编译并运行helloworld程序
$gcc-ohelloworldhelloworld.c
$./helloworld
正确的结果将在主机的显示器上打印如下字符串:
Hello,World!
4.编译在目标机运行的helloworld程序
$/usr/local/arm-linux/bin/arm-linux-gcc-ohelloworldhelloworld.c
由于编译器采用的是arm-linux-gcc编译器,因此使用上述命令编译出来的程序只能在ARM处理器上运行,不能在x86平台下运行,如果在RedHat中运行该程序将出现如下错误结果。
$./helloworld
bash:
./helloworld:
cannotexecutebinaryfile
5.下载helloworld程序到CVT-PXA270中调试
CVT-PXA270通过NFS将主机的/tftpboot/目录挂接到目标机的/mnt/nfs目录中,因此,需要将第四步编译的程序helloworld拷贝到主机的/tftpboot/目录或其子目录下。
$cphelloworld/tftpboot/examples/
在目标机端输入如下命令将主机端/tftpboot/目录挂接到/mnt/nfs/目录下:
#mount192.168.1.180:
/tftpboot//mnt/nfs
然后就可以运行helloworld程序:
#cd/mnt/nfs/examples/
#./helloworld
正确的结果将在超级终端(或MiniCom)上打印如下字符串:
Hello,World!
6.编写Makefile文件
使用vi编辑工具编辑Makefile,请注意文件名的M必须大写,其余为小写,如下所示。
注意其中每行前面的空格位置必须使用’Tab’键。
CC=/usr/local/arm-linux/bin/arm-linux-gcc
LD=/usr/local/arm-linux/bin/arm-linux-ld
EXEC=helloworld
OBJS=helloworld.o
CFLAGS+=
LDFLAGS+=
all:
$(EXEC)
$(EXEC):
$(OBJS)
$(CC)$(LDFLAGS)-o$@$(OBJS)$(LDLIBS$(LDLIBS_$@))
clean:
-rm-f$(EXEC)*.elf*.gdb*.o
使用如下命令编译ARM平台的helloworld程序。
$makeclean
$make
/usr/local/arm-linux/bin/arm-linux-gcc-c-ohelloworld.ohelloworld.c
/usr/local/arm-linux/bin/arm-linux-gcc-ohelloworldhelloworld.o
使用如下命令编译x86平台的helloworld程序。
$makeclean
$makeCC=gcc
gcc-c-ohelloworld.ohelloworld.c
gcc-ohelloworldhelloworld.o
分别参照步骤3和步骤5运行两种不同版本的程序,将得到相同的结果。
7.自己编写一个应用程序:
从键盘读入一个正整数num,计算0~num(包括num)范围内所有奇数之和,并打印输出;交叉编译这个应用程序,然后在ArmLinux平台上运行。
五、思考题
如果有多个源程序文件,应该如何编写Makefile?
实验三嵌入式Linux多任务应用程序设计
一、实验目的
1.了解多任务程序设计的基本原理;
2.掌握Linux下多任务程序设计的基本方法和相关库函数的使用。
二、实验设备
1.硬件:
PC机Pentium500以上,硬盘10G以上;
2.软件:
PC机操作系统,VMware-workstation-5或以上版本,LinuxReadHat操作系统。
三、实验原理
1.多进程
进程是指一个具有独立功能的程序在某个数据集合上的一次动态执行过程,它是系统进行资源分配和调度的基本单元。
进程有运行状态,就绪状态,睡眠状态,暂停状态,僵死态等多种状态。
进程控制编程相关函数:
(1)getpid()
在Linux中获得当前进程的进程号(PID)
(2)getppid()
在Linux中获得当前进程的父进程号(PPID)。
(3)fork()
用于从已存在的进程中创建一个新进程。
新进程称为子进程,而原进程称为父进程。
(4)wait()函数
在Linux系统中,一个进程结束了,但是他的父进程没有等待(调用wait/waitpid)他,那么他将变成一个僵尸进程。
wait()函数是用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。
如果该父进程没有子进程或者他的子进程已经结束,则wait()就会立即返回。
(5)waitpid()函数
waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能。
2.多线程
在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。
而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。
另外线程间具有非常方便的通信机制。
对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。
线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。
多线程程序设计:
Linux系统下的多线程遵循POSIX线程接口,称为pthread。
编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。
顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。
Clone()是Linux所特有的系统调用,它的使用方式类似fork。
下面是主要的多线程API函数:
(1)pthread_create
函数pthread_create用来创建一个线程,它的原型为:
externintpthread_create__P((pthread_t*__thread,__constpthread_attr_t*__attr,
void*(*__start_routine)(void*),void*__arg));
第一个参数为一个pthread_t类型的指向线程标识符的指针,pthread_t定义如下:
typedefunsignedlongintpthread_t;
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址最后一个参数是运行函数的参数。
如果不需要参数,该参数可以设为空指针。
当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。
前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。
创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。
(2)pthread_join
函数pthread_join用来等待一个线程的结束。
函数原型为:
externintpthread_join__P((pthread_t__th,void**__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。
这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。
(3)pthread_exit
一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。
它的函数原型为:
externvoidpthread_exit__P((void*__retval))__attribute__((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。
最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。
(4)pthread_cancel
用于终止其他线程。
类似于进程中的kill(pid,SIGKILL)函数。
intpthread_cancel(pthread_tthread);
参数thread是被终止的其他线程的标识符。
四、实验内容
编写一个程序,实现下列两个任务功能:
1.每隔1秒在屏幕上打印一个字符串“hello!
”
2.如果在键盘上按q键时,则停止打印,程序结束;如果按其余按键,则把所按的键在屏幕上打印出来。
五、