嵌入式Linux实验报告.docx

上传人:b****3 文档编号:5449030 上传时间:2022-12-16 格式:DOCX 页数:25 大小:462.34KB
下载 相关 举报
嵌入式Linux实验报告.docx_第1页
第1页 / 共25页
嵌入式Linux实验报告.docx_第2页
第2页 / 共25页
嵌入式Linux实验报告.docx_第3页
第3页 / 共25页
嵌入式Linux实验报告.docx_第4页
第4页 / 共25页
嵌入式Linux实验报告.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

嵌入式Linux实验报告.docx

《嵌入式Linux实验报告.docx》由会员分享,可在线阅读,更多相关《嵌入式Linux实验报告.docx(25页珍藏版)》请在冰豆网上搜索。

嵌入式Linux实验报告.docx

嵌入式Linux实验报告

嵌入式程序设计

实验报告

评语:

成绩

 

 

教师:

年月日

班级:

学号:

姓名:

地点:

EII-506

时间:

2013年6月

实验一开发环境的搭建与配置

【实验目的】

1)熟悉嵌入式Linux开发平台。

2)掌握嵌入式Linux开发平台的开发环境搭建与配置。

3)了解minicom配置串口通信参数的过程。

4)了解嵌入式Linux的启动过程。

5)掌握程序交叉编译运行及调试的一般方法。

6)掌握网络文件系统NFS的配置方法。

7)掌握嵌入式系统内核的编译、文件系统的打包及镜像的下载方法。

【实验内容】

1)连接实验开发板与宿主机。

2)在虚拟机中的CentOS(宿主机)搭建开发环境。

3)在宿主机中配置minicom。

4)分析嵌入式Linux的启动过程。

5)在宿主机上编写简单的C语言程序并用交叉编译工具进行编译,然后传输到目标机上运行。

6)在宿主机上编写简单的C语言程序并用交叉编译工具进行编译,用gdbserver进行远程调试。

7)配置NFS并用NFS进行文件拷贝。

8)嵌入式系统内核编译与文件系统的打包。

9)内核文件镜像与文件系统镜像的下载(从宿主机下载到目标机)。

【实验步骤】

连接实验开发板,对虚拟机进行设置

工具链的配置

tftp的安装

进入minicom软件,配置串口通信参数

有关串口通信选项的含义:

"Filenamesandpaths":

选择需要传输的文件和路径

"Filetransferprotocols":

选择传输文件的通信协议

"Serialportsetup":

设置串口通信参数

"Savesetupasdfl":

将设置好的各项参数保存为dfl

"Savesetupas":

将设置好的各项参数保存为自定义的文件名

"Exit":

退出返回到minicom设置好后的终端

"ExitfromMinicom":

从minicom命令中退出返回Linux终端

将光标移到"Serialportsetup",按回车键会弹出串口通信参数的配置菜单。

实验开发板的启动

嵌入式Linux系统的启动过程分析

1)启动Bootloader

Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于PC机上的BIOS。

在本系统中这段程序的起始地址为0x。

Bootloader在完成初始化RAM、初始化串口、检测处理器类型、设置Linux启动参数后,开始调用Linux内核。

本系统Linux内核镜像zImage放在Flash中,Bootloader首先把它拷贝到RAM中,然后跳转到RAM中对zImage进行解压缩。

解压缩后启动内核。

2)加载内核

内核启动后先进行一系列与内核相关的初始化,然后调用第一个用户进程——init进程并等待用户进程的执行。

具体的过程如下:

进行与体系结构相关的第一个初始化工作,首先通过检测出来的处理器类型进行处理器内核的初始化,然后进行内存结构的初始化,最后开启MMU,创建内核页表,映射所有的物理内存和IO空间;

创建异常向量表和初始化中断处理函数;

初始化系统核心进程调度器和时钟中断处理机制;

初始化串口控制台,在minicom中看到的系统启动过程中的信息都是通过串口输出的;

创建和初始化系统cache,为各种内存调用机制提供缓存,包括动态内存分配、虚拟文件系统及页缓存;

初始化内存管理,检测内存大小及被内核占用的内存情况;

初始化系统的进程间通信机制(IPC);

创建init进程,结束内核的启动。

3)执行init进程。

内核被加载后,第一个运行的程序便是/sbin/init,init进程是所有进程的发起者和控制者,它的进程号是1。

init进程首先读取/etc/inittab文件,并依据此文件来进行初始化工作(首先进行一系列的硬件初始化,然后通过命令行传递过来的参数挂载根文件系统。

最后执行一些其它的进程)。

init配置文件每行的基本格式为“id:

runlevel_ignored:

action:

process”,其中某些部分可以为空。

各部分的具体内容如下:

id:

指定启动进程的控制终端,如果所启动的进程并不是可以交互的shell,应该会有个控制终端(在PC机上该字段表示配置行的惟一标识)。

runlevel_ignored:

该字段是忽略掉的,配置inittab时空着它就行了(在PC机上该字段用来配置所启动进程适用的系统运行级别)。

4)执行/bin/login程序。

有些嵌入式系统在init进程执行完后会执行/bin/login。

login程序会提示使用者输入账号及密码,接着编码并确认密码的正确性,如果账号与密码相符,则为使用者初始化环境,并将控制权交给shell,即等待用户登录。

本系统在执行完init进程后直接开始执行/bin/sh,进入shell交互程序(跳过了执行/bin/login这一步)。

这个可以通过图27中的语句“ttyS0:

:

askfirst:

-bin/sh”来说明。

程序的交叉编译及运行

gdbserver远程调试

NFS的配置

内核配置与编译

文件系统的打包

内核与文件系统的下载

实验二并发Web服务器的实现

一、【实验目的】

1)熟悉Linux网络编程。

2)了解Web服务器原理。

3)掌握嵌入式Linux多进程、多线程、I/O多路复用三种方式并发服务器的实现。

二、【实验内容】

1)用多进程实现Web服务器。

2)用多线程实现Web服务器。

3)用I/O多路复用方式实现Web服务器。

三、【实验步骤】

1.环境配置

2.实现多进程Web服务器

1)用arm-linux-gcc命令编译源程序,得到可执行程序web_server_process。

2)用vi文本编译器创建文件index.html,用于测试Web服务器。

3)编辑文件index.html,然后保存并退出vi编辑器。

4)在/mnt/nfs/web目录下创建子目录cgi-bin,并用vi文本编辑器在cgi-bin目录下创建文件hello.cgi,用于测试Web服务器。

5)编辑文件hello.cgi,然后保存并退出vi编辑器。

6)用ls命令可以看到root用户对文件hello.cgi没有执行权限,通过chmod命令来修改hello.cgi的权限,使它称为可执行文件。

7)用命令service启动宿主机上的nfs服务,并用exportfs命令查看nfs的共享目录。

然后在目标机上挂载nfs

8)在目标机中运行web_server_process。

9)打开宿主机的浏览器,输入http:

//192.168.0.5/file,查看执行结果

10)在宿主机的浏览器中输入http:

//192.168.0.5,查看执行结果。

11)在宿主机的浏览器中输入http:

//192.168.0.5/index.html,查看执行结果。

12)在宿主机的浏览器中输入http:

//192.168.0.5/cgi-bin/hello.cgi,查看执行结果。

13)在宿主机的浏览器中输入http:

//192.168.0.5/web_server_process.c,查看执行结果。

3.实现多线程Web服务器

1)用arm-linux-gcc命令编译源程序,得到可执行程序web_server_thread。

2)在目标机中运行web_server_thread。

3)在宿主机的浏览器中输入http:

//192.168.0.5,查看执行结果。

4)在宿主机的浏览器中输入http:

//192.168.0.5/cgi-bin/hello.cgi,查看执行结果。

5)在宿主机的浏览器中输入http:

//192.168.0.5/web_server_thread.c,查看执行结果。

4.实现I/O多路复用方式的Web服务器

1)用arm-linux-gcc命令编译源程序,得到可执行程序web_server_select。

2)在目标机中运行web_server_select。

3)在宿主机的浏览器中输入http:

//192.168.0.5,查看执行结果。

4)在宿主机的浏览器中输入http:

//192.168.0.5/cgo-bin/hello.cgi,查看执行结果。

5)在宿主机的浏览器中输入http:

//192.168.0.5/web_server_select.c,查看执行结果。

实验三嵌入式Linux驱动

一、【实验目的】

1)熟悉嵌入式Linux驱动程序编写框架。

2)了解七段数码管驱动程序的工作原理,熟练掌握该驱动程序在嵌入式开发平台的移植和注册使用。

3)了解16键矩阵键盘驱动程序的工作原理,熟练掌握该驱动程序在嵌入式开发平台的移植和注册使用。

二、【实验内容】

1)学习Linux驱动源代码,分析代码中各个函数模块的功能作用。

2)在宿主机上交叉编译七段数码管驱动程序,然后移植到目标机上。

3)在目标机上注册驱动程序,验证驱动的功能。

三、【实验步骤】

1.了解七段数码管工作原理

七段数码管是显示数字的电子元件,因为借助七个发光二极管以不同组合来显示数字,所以称为七段数码管(如图1)。

七段数码管分为共阴极和共阳极,共阳极的七段数码管的正极(或者阳极)为八个发光二极管的共有正极,其他接点为独立发光二极管的负极(或者阴极),使用者只需要把正极接电,不同的负极接地就可以控制七段数码管显示不同的数字。

共阴极的七段数码管与共阳极的只是接电的接法相反而已。

图1

2.开发板七段数码管电路介绍

开发板上有四个七段共阴数码管,2个一组,第一组七段数码管使用系统LED_CS2作为其位选使能信号,两个数码管的段选信号分别使用数据总线的D0~D7位和D8~D15位,如图2所示。

图2

第二组七段数码管使用系统LED_CS3作为其位选使能信号,两个数码管的段选信号分别使用数据总线的D0~D7位和D8~D15位,如图3所示。

图3

分析可知,对七段数码管的操作主要是对其位选和段选信号的控制。

中位选信号决定显示哪个七段数码管,段选信号决定其显示的字型信息(共阴极七段数码管段选控制信息如表1),这也是驱动程序和硬件关联的主要部分。

D7

D6

D5

D4

D3

D2

D1

D0

字型

Dp

G

F

E

D

C

B

A

编码

0

0

1

1

1

1

1

1

1

0X3F

1

0

0

0

0

0

1

1

0

0X06

2

0

1

0

1

1

0

1

1

0X5B

3

0

1

0

0

1

1

1

1

0X4F

4

0

1

1

0

0

1

1

0

0X66

5

0

1

1

0

1

1

0

1

0X6D

6

0

1

1

1

1

1

0

1

0X7D

7

0

0

0

0

0

1

1

1

0X07

8

0

1

1

1

1

1

1

1

0X7F

9

0

1

1

0

1

1

1

1

0X6F

A

0

1

1

1

0

1

1

1

0X77

B

0

1

1

1

1

1

0

0

0X7C

C

0

0

1

1

1

0

0

1

0X39

D

0

1

0

1

1

1

1

0

0X5E

E

0

1

1

1

1

0

0

1

0X79

F

0

1

1

1

0

0

0

1

0X71

表1

3.七段数码管驱动程序分析

1)添加驱动程序所需的头文件和变量:

SEG_CS1和SEG_CS2就是上面硬件接口所提及的两组七段数码管的位选使能信号,LED[10]数组中保存的就是在共阴极数码管上面显示0~9的段选信号。

Seg这个结构体用于保存4个数码管即时显示的数字的段选信号。

#include

#include

#include

#include

#include

MODULE_LICENSE("GPL");//用于声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时将收到内核被污染(kerneltainted)的警告

charLED_MODULE=0;

#defineDEVICE_NAME"xidian_seg7"

#defineSEG_CS10x

#defineSEG_CS20x

staticcharLED[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F};

unsignedlong*CS1_Address,*CS2_Address;

structseg

{

charLED1_Val;

charLED2_Val;

charLED3_Val;

charLED4_Val;

charnegative;

};

2)同时更新所有七段数码管驱动显示函数:

CS1_address对应第一组七段数码管的位选信号,该组第一个数码管的段选信号保存在short变量的低8位,该组第二个数码管的段选信号保存在short变量的高8位。

CS2_address对应第二组七段数码管,其余操作和第一组的七段数码管一致。

staticvoidUpdateled(structseg*seg_7)

{

unsignedshortbuff=0x00;

buff=seg_7->LED1_Val;

buff=buff|(seg_7->LED2_Val<<8);

writew(buff,CS1_Address);

buff=0x00;

buff=seg_7->LED3_Val;

buff=buff|(seg_7->LED4_Val<<8);

writew(buff,CS2_Address);

return;

}

3)写具体某位七段数码光驱动管显示函数:

position对应的是4个七段数码管的相对位置,value就是需要更新的七段数码管要显示数字的段选信号值。

voidvalue_seting(structseg*seg_7,charposition,charvalue)

{

if(seg_7->negative==0)

value=~value&~(0x1<<7);

else

value=(0x1<<7)|value;

if(position==1)

seg_7->LED1_Val=value;

elseif(position==2)

seg_7->LED2_Val=value;

elseif(position==3)

seg_7->LED3_Val=value;

elseif(position==4)

seg_7->LED4_Val=value;

}

4)实现七段数码管驱动写操作函数:

把用户写入的数码管显示更新数据,转换成为要显示数字对应的段选信号,并且保存在led_forall数组中,并且调用Value_setting更新显示数据,最后调用Updateled()更新实际的数码管显示信息。

staticssize_tseg7_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos)

{

inti;

structseg*seg_7=file->private_data;

charled_forall[4];

printk(KERN_EMERG"TheModuleiswritten,seg7_write\n");

if(count!

=4)

{

printk(KERN_EMERG"thecountofinputisnot4!

!

");

return0;

}

if(copy_from_user(led_forall,buffer,4))

return–EFAULT;

for(i=1;i<=4;i++)

{

value_seting(seg_7,i,LED[(int)led_forall[i-1]]);

}

Updateled(seg_7);

return0;

}

5)实现七段数码管驱动IOCTL操作函数。

staticintseg7_ioctl(structinode*ip,structfile*fp,unsignedintcmd,unsignedlongarg)

{

charval=0x00;

structseg*seg_7=fp->private_data;

if(!

arg)

return-EINVAL;

if(copy_from_user(&val,(int*)arg,sizeof(char)))

return-EFAULT;

switch(cmd){

case1:

value_seting(seg_7,1,val);

break;

case2:

value_seting(seg_7,2,val);

break;

case3:

value_seting(seg_7,3,val);

break;

case4:

value_seting(seg_7,4,val);

break;

case0:

seg_7->negative=LED_MODULE;

break;

default:

printk(KERN_EMERG"ioctlparameterinputerror,pleaseinputnumber0-4");

break;

}

Updateled(seg_7);

return0;

}

6)实现七段数码管驱动打开操作函数。

staticintseg7_open(structinode*inode,structfile*filp)

{

structseg*seg_7;

printk(KERN_EMERG"TheModuleisopen,seg7_open\n");

seg_7=kmalloc(sizeof(structseg),GFP_KERNEL);//分配内存(在内核空间)seg_7->negative=LED_MODULE;

filp->private_data=seg_7;

return0;

}

7)实现七段数码管驱动释放函数。

staticintseg7_release(structinode*inode,structfile*filp)

{

printk(KERN_EMERG"TheModuleisrelease,seg7_release\n");

kfree(filp->private_data);

return0;

}

8)七段数码管驱动文件结构体定义:

定义七段数码管驱动程序的打开,写入,释放,Ioctl操作,属主信息。

staticstructfile_operationsEmdoor_fops={

open:

seg7_open,

write:

seg7_write,

release:

seg7_release,

ioctl:

seg7_ioctl,

owner:

THIS_MODULE,

};

9)实现七段数码管驱动初始化函数:

映射七段数码管的位选信号的物理实际地址,注册设备。

staticint__initseg7_init(void)

{

intret;

printk(KERN_EMERG"TheModuleisInit,seg7_init\n");

CS1_Address=ioremap(SEG_CS1,4);

CS2_Address=ioremap(SEG_CS2,4);

ret=register_chrdev(56,DEVICE_NAME,&Emdoor_fops);

if(ret<0){

printk(DEVICE_NAME"can'tgetmajornumber\n");

returnret;

}

return0;

}

10)实现七段数码管驱动模块退出函数与模块描述:

取消对七段数码管的位选信号的物理地址的映射,释放设备。

staticvoid__exitseg7_exit(void)

{

printk(KERN_EMERG"TheModuleisExit,seg7_exit\n");

iounmap(CS1_Address);

iounmap(CS2_Address);

unregister_chrdev(56,DEVICE_NAME);

}

module_init(seg7_init);

module_exit(seg7_exit);

MODULE_AUTHOR("Mr.han");

MODULE_DESCRIPTION("Thisisa7SegmentLeddriverdemo");

11)七段数码管驱动程序的Makefile

CFLAGS+=$(DEBFLAGS)-Wall

ifneq($(KERNELRELEASE),)

obj-m:

=xidian_seg7.o

else

KERNELDIR?

=../linux-2.6

PWD:

=$(shellpwd)

ALL:

$(MAKE)$(CFLAGS)-C$(KERNELDIR)M=$(PWD)modules

endif

clean:

rm-fr*.o*.ko*.symvers*~core.depend.*.cmd*.mod.c.tmp_versions

4.编写七段数码管驱动的测试程序和Makefile文件

1)seg7_test.c源代码:

#include

#include

#include

#include

#include

typedefunsignedcharu8;

#defineSEG_DEV"/dev/xidian_seg7"

charnumber[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F};

voidclear_led(intfd)

{

inti;

charval=0;

for(i=1;i<=4;i++)

{

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1