实验报告(2011/2012学年第二学期)课程名称ARM嵌入式系统原理与开发实验名称嵌入式Linux交叉开发环境建立与程序开发实验时间2014年5月21日指导单位通信与信息工程学院指导教师余雪勇学生姓名班级学号学院(系)通信与信息工程专业电子信息工程实验一:熟悉Linux开发环境实验目的:熟悉Linux开发环境,学会基于S3C2410的Linux开发环境的配置和使用,学习使用Linux操作系统的常用命令。使用Linux的armv4l-unknown-linux-gcc编译,使用基于NFS方式的下载调试,了解嵌入式开发的基本过程。实验内容与要求:使用RedhatLinux9.0操作系统环境,安装ARM-Linux的开发库及编译器。创建一个新目录,并在其中编写hello.c和Makefile文件。学习在Linux下的编程和编译过程,以及ARM开发板的使用和开发环境的设置。下载已经编译好的文件到目标开发板上运行。学会集成环境的安装与开发。预备知识C语言的基础知识、程序调试的基础知识和方法,Linux的基本操作。实验设备及工具(包括软件调试工具):硬件:UP-NETARM2410-S嵌入式实验平台、PC机Pentium500以上,硬盘10GB以上。软件:PC机操作系统REDHATLINUX9.0+MINICOM+ARM-LINUX开发环境。实验过程:1、建立工作目录运行PC机上的Linux系统,进入系统后,建立工作目录,所用语句如下:[root@zxtsmile]#mkdirhello[root@zxtsmile]#cdhello2、编写程序源代码编写的hello.c如下:#includestdio.hmain(){printf(“helloworld\n”);}3、编写Makefile要使上面的hello.c程序能够运行,必须要编写一个Makefile文件,Makefile文件定义了一系列的规则,它指明了哪些文件需要编译,哪些文件需要先编译,哪些文件需要重新编译等等更为复杂的命令。本次实验所用的Makefile文件如下:CC=armv4l-unknown-linux-gccEXEC=helloOBJS=hello.oCFLAGS+=LDFLAGS+=–staticall:$(EXEC)$(EXEC):$(OBJS)$(CC)$(LDFLAGS)-o$@$(OBJS)clean:-rm-f$(EXEC)*.elf*.gdb*.o使用如下语句来创建Makefile文件:[root@zxthello]#viMakefile4、编译应用程序接下来,进行hello.c的编译,使用以下语句:[root@zxthello]#makeclean[root@zxthello]#make5、下载调试在宿主PC计算机上启动NFS服务,并设置好共享的目录,进入MINICOM中建立开发板与宿主PC机之间的通讯。[root@zxthello]#minicom[/mnt/yaffs]mount-tnfs-onolock192.168.0.56:/arm2410s/host实验二:多线程应用程序设计实验目的:1.了解多线程程序设计的基本原理。2.学习pthread库函数的使用。实验内容:读懂pthread.c的源代码,熟悉几个重要的PTHREAD库函数的使用。掌握共享锁和信号量的使用方法。进入/arm2410s/exp/basic/02_pthread目录,运行make产生pthread程序,使用NFS方式连接开发主机进行运行实验。预备知识:硬件:UP-TECHS2410/P270DVP嵌入式实验平台,PC机Pentium500以上,硬盘40G以上,内存大于128M。软件:PC机操作系统REDHATLINUX9.0+MINICOM+ARM-LINUX开发环境。实验原理及代码分析:1.多线程程序的优缺点多线程程序作为一种多任务、并发的工作方式,有以下的优点:1)提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(timeconsuming)置于一个新的线程,可以避免这种尴尬的情况。2)使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。3)改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。LIBC中的pthread库提供了大量的API函数,为用户编写应用程序提供支持。2.实验源代码与结构流程图*Theclassicproducer-consumerexample.*Illustratesmutexesandconditions.*byZoujianguoah_zou@tom.com*2003-12-22#includestdio.h#includestdlib.h#includetime.h#includepthread.h#defineBUFFER_SIZE16/*设置一个整数的圆形缓冲区*/structprodcons{intbuffer[BUFFER_SIZE];/*缓冲区数组*/pthread_mutex_tlock;/*互斥锁*/intreadpos,writepos;/*读写的位置*/pthread_cond_tnotempty;/*缓冲区非空信号*/pthread_cond_tnotfull;/*缓冲区非满信号*/};/*--------------------------------------------------------*//*初始化缓冲区*/voidinit(structprodcons*b){pthread_mutex_init(&b-lock,NULL);pthread_cond_init(&b-notempty,NULL);pthread_cond_init(&b-notfull,NULL);b-readpos=0;b-writepos=0;}/*--------------------------------------------------------*//*向缓冲区中写入一个整数*/voidput(structprodcons*b,intdata){pthread_mutex_lock(&b-lock);/*等待缓冲区非满*/while((b-writepos+1)%BUFFER_SIZE==b-readpos){printf(waitfornotfull\n);pthread_cond_wait(&b-notfull,&b-lock);}/*写数据并且指针前移*/b-buffer[b-writepos]=data;b-writepos++;if(b-writepos=BUFFER_SIZE)b-writepos=0;/*设置缓冲区非空信号*/pthread_cond_signal(&b-notempty);pthread_mutex_unlock(&b-lock);}/*--------------------------------------------------------*//*从缓冲区中读出一个整数*/intget(structprodcons*b){intdata;pthread_mutex_lock(&b-lock);/*等待缓冲区非空*/while(b-writepos==b-readpos){printf(waitfornotempty\n);pthread_cond_wait(&b-notempty,&b-lock);}/*读数据并且指针前移*/data=b-buffer[b-readpos];b-readpos++;if(b-readpos=BUFFER_SIZE)b-readpos=0;/*设置缓冲区非满信号*/pthread_cond_signal(&b-notfull);pthread_mutex_unlock(&b-lock);returndata;}/*--------------------------------------------------------*/#defineOVER(-1)structprodconsbuffer;/*--------------------------------------------------------*/void*producer(void*data){intn;for(n=0;n1000;n++){printf(put--%d\n,n);put(&buffer,n);}put(&buffer,OVER);printf(producerstopped!\n);returnNULL;}/*--------------------------------------------------------*/void*consumer(void*data){intd;while(1){d=get(&buffer);if(d==OVER)break;printf(%d--get\n,d);}printf(consumerstopped!\n);returnNULL;}/*--------------------------------------------------------*/intmain(void){pthread_tth_a,th_b;void*retval;init(&buffer);pthread_create(&th_a,NULL,producer,0);pthread_create(&th_b,NULL,consumer,0);/*等待生产者和消费者结束*/pthread_join(th_a,&retval);pthread_join(th_b,&retval);return0;}3.主要函数分析:下面我们来看一下,生产者写入缓冲区和消费者从缓冲区读数的具体流程,生产者首先要获得互斥锁,并且判断写指针+1后是否等于读指针,如果相等则进入等待状态,等候条件变量notfull;如果不等则向缓冲区中写一个整数,并且设置条件变量为notempty,最后释放互斥锁。消费者线程与生产者线程类似,这里就不再过多介绍了。流程图如下:生产者写入共享的循环缓冲区函数PUTvoidput(structprodcons*b,intdata){pthread_mutex_lock(&b-lock);//获取互斥锁while((b-writepos+1)%BUFFER_SIZE==b-readpos){//如果读写位置相同pthread_cond_wait(&b-notfull,&b-lock);//等待状态变量b-notfull,不满则跳出阻塞}b-buffer[b-writepos]=data;//写入数据b-writepos++;if(b-writepos=BUFFER_SIZE)b-writepos=0;pthread_cond_signal(&b-notempty);//设置状态变量pthread_mutex_unlock(&b-lock);//释放互斥锁}消费者读取共享的循环缓冲区函数GETintget(structprodcons*b){intdata;pthread_mutex_lock(&b-lock);//获取互斥锁while(b-writepos==b-readpos){//如果读写位置相同pthread_cond_wait(&b-notempty,&b-lock);//等待状态变量b-notempty,不空则跳出阻塞。否则无数据可读。}data=b-buffer[b-readpos];//读取数据b-readpos++;if(b-readpos