为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

通过Web浏览器控制开发板硬件

2012-11-01 19页 doc 481KB 74阅读

用户头像

is_081154

暂无简介

举报
通过Web浏览器控制开发板硬件嵌入式Linux 开发环境的建立 V1.0 【版本信息】 2010年4月28日 杨哲 编写初始版本V1.0 由于开发板采用的是CarmFS 文件系统,CramFS 文件系统为只读文件系统,不能添加和修改文件。为了以后可以随时修改、配置开发环境,所以我们按自己的要求制作好根文件系统,具体步骤如下: 本手册的一些约定: 1) 工作目录为:/up-Star2410。 2) 手册中的命令默认情况下,是在pc机的终端下输入的,如果在arm中输入的命令,文中会特别注明。 1、 安装交叉编译器 我们这里选用友善之臂提...
通过Web浏览器控制开发板硬件
嵌入式Linux 开发环境的建立 V1.0 【版本信息】 2010年4月28日 杨哲 编写初始版本V1.0 由于开发板采用的是CarmFS 文件系统,CramFS 文件系统为只读文件系统,不能添加和修改文件。为了以后可以随时修改、配置开发环境,所以我们按自己的要求制作好根文件系统,具体步骤如下: 本手册的一些约定: 1) 工作目录为:/up-Star2410。 2) 手册中的命令默认情况下,是在pc机的终端下输入的,如果在arm中输入的命令,文中会特别注明。 1、 安装交叉编译器 我们这里选用友善之臂提供的4.3.2版本,相比3.x.x版本,4.3.2的交叉编译器采用EABI技术(EABI的全称是:Embedded Application Binary Interface),它针对软件浮点数运行做了优化,使用它编译出来的应用程序效率更高,不过也有一个不好的地方:就是和以前版本编译的应用程序不兼容了,全部都需要程序编译 所以我们这里统一只使用4.3.2版本,在PC机上,具体安装步骤如下: # cd /up-Star2410 #  tar -zxvf  arm-linux-gcc-4.3.2.tgz 解压后的目录为usr目录,将usr的子目录4.3.2拷贝到根目录/usr/local/arm下 然后 # vi /root/.bash_profile 将里边的PATH修改为 PATH=$PATH:HOME/bin:/usr/local/arm/4.3.2/bin/ 保存退出,执行: # source /root/.bash_profile 则以后的arm-linux-gcc-4.3.2会被自动搜索到 验证是否正确安装: 在终端上输入ar,然后双击tab键,会自动显示arm-linux-gcc-4.3.2,如果同时显示了以前的旧版本,则需重新启动虚拟机 2、 烧写内核镜像和根文件系统 由于内核镜像和根文件系统都存储在64MB的NAND Flah上,首先了解一下NAND Flah的分区情况: 名称 起始地址 结束地址 大小 作用 Boot Agent 0x00000000 0x00080000 0.5M 启动u-boot S3C2410 kernel 0x00080000 0x00280000 2M Linux内核镜像 S3C2410 rootfs 0x00280000 0x00680000 4M 根文件系统,只读,cramfs user 0x00680000 0x04000000 57.5M 用户文件系统,可读,yaffs 注意:第四个分区user是yaffs2格式,可读,系统启动时会把user挂载到根文件系统的root目录下,所以root目录是可读的,并有57.5M的空间供用户使用,但是其它目录还是不可写的。 1) 制作根文件系统包 由于时间原因,本手册并未给出制作根文件系统的具体步骤(后续手册中会具体写到) # cd /up-Star2410 # tar –zxvf rootfs.tar.gz # ./mkfs.cramfs rootfs root.cramfs 这就生成了cramfs包,然后把它拷贝到tftp下载目录(本机为跟目录tftpboot),下一步要烧写到flash中 2) 制作内核镜像uImage 源码已经提供,直接把uImage复制到tftfboot目录下用就可以了,具体怎么裁剪和编译内核请看后续手册。 3) 烧写内核镜像和cramfs文件系统 注意:下载需用到tftp服务器,所以必须确保系统已经安装tftp服务器,下面验证你的系统是否已经安装了tftp服务器: #service xinetd restart #netstat –a | grep tftp 出现下图明你已经安装了tftp服务器 ①、配置bootloader 重启开发板,马上按下enter键, 在提示符下输入setenv serverip 192.168.1.137,此IP为我们虚拟机的IP,再输入setenv ipaddr 192.168.1.193,此IP为我们开发板的IP。最好输入saveenv,保存设置,之后就不需要改动了。 设置之后,我们可以通过printenv指令,查看u-boot的环境变量中已经添加了新的变量,如图(如果不是,请按开发板带的快速手册中的烧写部分烧写) 这时,我们的u-boot的配置就结束了。 ②、在配置好u-boot之后,执行烧写内核的命令,输入run update_kernel指令,如图。 ③、烧写根文件系统 执行烧写根文件系统的命令,输入run update_rootfs指令,如图 然后输入boot启动linux系统,至此开发板的环境已经建立好了。 特别注意:以后我们要不断的向根文件系统中添加相应的功能,需要随时更新系统,按照上述步骤执行就可以了。 这里有必要对开发板的部分启动信息进行一些解释 前三行表明开发板中的boa服务器已经启动,端口号是80。 (boa服务器的移植请看后续手册) 第四行表明user分区(即/dev/mtdblock3)已经挂载到root目录下,可以看到它是yaffs文件格式。 最后一行 [root@yangzhe]# 中的yangzhe是我自己设置的,有兴趣的话可以在根文件系统中的/etc/profile中修改PS1的值,修改为自己喜欢的格式,如下: # cd /up-Star2410/rootfs/etc # vi profile 修改完后更新根文件系统。 基于Boa的Web服务器设计 1、Boa服务器功能概述和实现 Boa是一款单任务的HTTP服务器,与其他传统的Web服务器不同的是当有连接请求到来时,它并不为每个连接单独创建进程,也不通过复制自身进程来处理多链接,而是通过建立HTTP请求列表来处理多路HTTP连接请求,同时它只为CGI程序创建新的进程,这样就在最大程度上节省了系统资源,这对嵌入式系统来说至关重要。同时它还具有自动生成目录、自动解压文件等功能,因此,Boa具有很高的HTTP请求处理速度和效率,在嵌入式系统中具有很高的应用价值。[14] 嵌入式Web服务器Boa和普通Web服务器一样,能够完成接收客户端请求、请求、响应请求、向客户端返回请求结果等任务。它的工作过程主要包括: 1. 完成Web服务器的初始化工作,如创建环境变量、创建TCP套接字、绑定端口、开始侦听、进入循环结构,以及等待接收客户浏览器的连接请求; 2. 当有客户端连接请求时,Web服务器负责接收客户端请求,并保存相关请求信息; 3. 在接收到客户端的连接请求之后,分析客户端请求,解析出请求的方法、URL目标、可选的查询信息及表单信息,同时根据请求做出相应的处理; 4. Web服务器完成相应处理后,向客户端浏览器发送响应信息,关闭与客户机的TCP连接。嵌入式Web服务器Boa根据请求方法的不同,做出不同的响应。 Boa的功能实现也是通过建立连接、绑定端口、进行侦听、请求处理等来实现的。嵌入式Web服务器由于嵌入式系统资源非常有限,不能直接使用桌面或服务器上的Web服务器。Boa是一个单任务的HTTP服务器,它并不为每个新的连接启动新的进程,也不为多重连接而自我复制进程,而是内部并行处理所有的连接。Boa也遵循GNU协议,完全免费,完全开放源代码。 3、 移植Boa到开发平台 具体移植步骤请参看BOA服务器的移植文档。 这里我们使用的文件系统中已经移植好了boa服务器,只要知道怎么使用就可以了,这里需要说明几点: ①交叉编译好的boa可执行文件我们放在/sbin 目录下 ②boa服务器的配置文件放在/etc/boa目录下,如果需要需该参数可以在这里修改 ③boa服务器的主目录我们设置在/root/web下,这个目录很重要,它存放HTML文档,就是我们制作的网页。 ④cgi脚本路径我们设置在/root/web/cgi-bin目录下,这里存放cgi程序。 4、 测试静态网页 boa移植好之后,我们就可以在windows下的浏览器访问开发板(/root/web)上的HTML页面了,下面我们复制已经准备好的页面到开发板中,进行测试。 在arm端挂载NFS共享目录: # mount –t nfs –o nolock 192.168.1.137:/up-Star2410 /mnt/nfs # cd /mnt/nfs 复制虚拟机下/up-Star2410下的web目录到开发板的root目录下 # cp –rf web /root 注意:有时可能不能通过nfs向开发板的root目录下复制文件,请使用其它方法传输文件。 接下来在主机的浏览器地址栏输入http://192.168.1.3/LXI-home.html,其中192.168.1.3是开发板的IP地址,该地址可能随时改变,观察在客户机的浏览器中的连接请求结果(如图)和在开发板上的服务器的打印信息。 5、 通用网关接口CGI 前面我们实现了在客户端请求开发板上的网页,但是我们的目标是通过在客户端上控制开发板上的LED灯,那么现在的问题是怎么把客户机上的信息传到开发板上,实现真正的双向交互,这里我们选用CGI程序,它是嵌入式Web服务器的首选,在桌面领域则还有很多其他形式的动态网页,比如ASP、JSP、PHP等 ①CGI 的概念 CGI(Common Gateway Interface) 通用网关接口的简称。其主要的功能是在WWW 环境 下,从客户端传递一些信息给Web 服务器,再由Web 服务器去启动所指定的程序来完成特定的工作。所以简单点说,CGI 是一种通用的接口标准。 CGI 可以为我们提供许多HTML(HyperText Markup Language,超文本标记语言)无法 做到的功能。比如一个计算器、顾客表格的提交以及统计、搜索引擎、Web 数据库等等。 用HTML 是没有办法记住客户的任何信息的。要把顾客的信息记录在服务器的硬盘上,就 要用到CGI。 ②CGI 的工作原理 CGI 是一种通用的接口标准。CGI 程序就是符合这种接口标准的,运行在Web 服务器 上的程序。它的工作就是控制信息要求,产生并传回所需的文件。CGI 由浏览器的输入触发这个程序。 先看看浏览器浏览网页是怎样实现的。作为一个用户首先在浏览器的地址栏中添加上要 访问的主页地址并回车触发这个申请。浏览器将申请发送到服务器上。Web 服务器接收这 些申请并根据.htm 或.html 的后缀并认识到这是HTML 文件。Web 服务器从当前硬盘或内存中读取正确的HTML 文件,然后将它送回浏览器。HTML 文件将被用户的浏览器解释并将结果显示在用户浏览器上。 CGI 程序可以用来在web 内加入动态的内容。通过接口,浏览器能够发送一个可执行 应用程序的HTTP 请求,而不仅仅只是静态的HTML 文件。服务器运行指定的应用程序, 这个应用程序读取与请求相关的信息,获得请求传过来的数值。例如使用者填写HTML 表 单提交了数据,浏览器将这些数据发送到Web 服务器上。Web 服务器接收这些数据并根据 客户机指定的CGI 程序把这些数据递交给指定的CGI 程序,并使CGI 在服务器上运行。CGI 程序运行结束,生成HTML 页面,Web 服务器把CGI 程序运行的结果送回用户浏览器。HTML文件将会被用户的浏览器解释并将结果显示在用户浏览器上。CGI 的基本工作情况如下图所示: HTTP请求 执行 调用 URL 格式文档 运行结果 返回 ③CGI的输入与输出 Web 服务器与CGI 程序之间通过四种途径进行通信: 环境变量、命令行、标准输入和 标准输出。其中负责输入的有环境变量、命令行和标准输入。命令行只用于ISINDEX 查询, 较少使用。环境变量存放服务器向CGI 程序传递的一些运行参数, 比REQUEST_METHOD 表示用户提出请求或提交数据的方法是GET 还是POST。方法(METHOD) 是HTTP 中对命令的称呼。GET 方法通过环境变量QUERY- STRING 传递用户提交的数据。经过编码的数据以问号打头追加在标识CGI 脚本地址的URL 后一起传给Web 服务器。服务器将其存于QUERYSTRING中, CGI 程序可以通过getenv( )函数来读取。编码数据除了表单数据, 还可以是直接调用CGI 脚本时追加在URL 地址后面的参数。POST 方法则通过标准输入( stdin) 传递提交数据。编码了的表单数据独立地传送给Web 服务器, CGI 程序从标准输入中获得, 可以用getchar( ), sscanf( ), fread( )等函数。要注意的是数据的长度是通过读取环境变量CONTENT_LENGTH 获得的, 而不是通过文件尾标识符来判断。 ④CGI 编程语言的选择 CGI程序可以用任何程序设计语言编写,如shell脚本语言、Perl、Fortran、Pascal、C语言等。不过在嵌入式系统中,由于C语言编写的CGI程序具有执行速度快、内存开销小且安全性高(因为C语言程序是编译执行且不可被修改)等特点,应用更为广泛一些。 ⑤CGI 程序的使用方法 一般而言,要使用CGI 程序就必须在Web 网页中迁入调用CGI 程序的代码。通常的做法有三种,一是通过表单调用,二是通过超链接调用,三是通过SSI 调用。这里着重阐述 使用表单调用CGI 程序的办法。 那么如何将数据通过表单提交给CGI 程序了,下面是一个简单的表单: 对应的源代码是 简单LED测试

简单LED测试(CGI实现)

led1 led2 led3

网页中表单由字头
开始,
结束。其中action=“/cgi-bin/led.cgi”指明使用的CGI 程序名为led.cgi;method 属性指定提交数据的方法(POST 还是GET),这里使用的是GET 方法。 这个实例中,有三个复选框按钮,它们的名字是led1,led2,led3,对应的值是1,2,3。这里首先了解一下CGI编码的规则。规则如下:不同域(变量值对)之间用“&”分开;变量与值之间用“=”连接;空格符用“+”代替;任何特殊字符用“%”接相应的十六进制ASCII 码代替,最后形成的格式为:name1=value1&name2=value2%name3=value3 ...。假如用户选中了led1,然后点击提交按钮,那么表单中的数据就会被编码。最好形成的编码如下:led1=1; 如果选中led2,则形成的编码如下:led2=2;如果选中led2和led3,则最后提交给服务器的数据形式是:led2=2&led3=3,其他依次类推。 这样编码之后,客户端浏览器就会把如led2=2&led3=3传到action所指的服务器端程序中如/cgi-bin/led.cgi,开发板中的led.cgi程序将上面的编码解析后,就知道用户进行了哪些操作。 ⑥ CGI 程序的编写 对于CGI 程序来讲,当采用GET 方式提交数据时,用户提交的数据放在环境变量QUERY_STRING 中。CGI 程序从环境变量QUERY_STRING 获得数据。为了解释和执行程序,CGI 必须要分析(处理)这个字符串。当你想从服务器获得数据并且不改变服务器上的数据时,应该选用GET。但是用GET 方式提交时,数据不经过CGI 编码,而且数据长度不能超过1K 字节。否则只能用POST 方式了。 CGI 程序的任务大概有两部分,输入任务和输出任务。输入任务就是指获取用户提交数据的过程。输入任务大概分以下几个步骤:(1)首先从CGI 环境变量REQUESR_METHOD中获取CGI 程序的提交方式;(2)根据提交方式的不同取出变量名和变量值。如果是Get方式,从环境变量QUERY_STRING 中取出编码数据;如果是POST 方式,从标准输入输出中读取相应的字符串,读取长度有环境变量CONTENT_LENGTH 决定。(3)根据CGI 编规则取出字符串中的数据(变量名和变量值对)。 在输出任务完成后,我们得到所有的变量名和变量值对,而后就是输出任务。输出任务主要有三个:(1)输出HTTP 响应的头标志。如printf(“Content-type:text/html\n\n”);它告诉Web 服务器随后的输出是以HTML 文本形式输出的。注意这个头信息中有两个换行符,这是因为Web 服务器需要再实际的文本信息开始之前先看见一个空行。(2)调用其它程序(如测量程序、设置参数的程序、或者查询数据库的程序)。(3)输出CGI 程序执行结果。 简单LED控制(CGI实现) 现在设计一个简单的LED控制页面。有三个复选框按钮,对应开发板3个LED灯,目标是可以任意控制开发板上的3个LED灯。 首先安装LED灯驱动,这里我们提供了编译好的驱动模块,通过NFS方式把mini2410-leds.ko和test_led复制到开发板的root目录下,然后在arm终端执行: # insmod mini2410-leds.ko 查看新加设备对应的主设备号: # cat /proc/devices 231 leds 手动创建设备节点: #mknod /dev/leds c 231 0 下来测试led驱动是否装好 #./test_led 0 1 看第一个LED灯是否亮了,如果没亮就说明驱动没有加载上。 CGI程序:(此程序对应上面的网页) cgi_led.c:(此源码放在web文件夹中的cgi-bin中) #include #include #include #include #include #include #include #include #include #define MAX_ARG 150 /* 此函数通过识别‘&’和‘=’,对客户端传来的数据进行解析,以下的解析过程有些复杂,还有待完善。 */ unsigned int paraExtract(unsigned int pos, unsigned char *pIn, unsigned char *pOut, unsigned char *pValue) { unsigned int count = 0; while(*(pIn + pos) != '&') { if(*(pIn + pos) == '\0') { *(pValue + 1) = '\0'; return 0xffff; } *(pOut + count) = *(pIn + pos); if(*(pIn + pos) == '=') { *pValue = *(pIn + pos + 1); *(pOut+count) = '\0'; } pos++; count++; } *(pValue + 1) = '\0'; return (pos + 1); } int main() { /*读取环境变量"QUERY_STRING"得到参数字符串*/ char *buf = getenv("QUERY_STRING"); //printf("%s\n", getenv("QUERY_STRING")); char para1[MAX_ARG], para2[MAX_ARG],para3[MAX_ARG]; char value1[MAX_ARG], value2[MAX_ARG],value3[MAX_ARG]; /*对数组初始化,否则,会出现乱码*/ para1[0] = '\0'; para2[0] = '\0'; para3[0] = '\0'; value1[0] = '\0'; value2[0] = '\0'; value3[0] = '\0'; unsigned int extractEnd = 0; unsigned int extractTemp = 0; unsigned int n=0; if (buf == NULL) { value1[0]=0; value2[0]=0; value3[0]=0; } else { while(1) { extractTemp = paraExtract(extractEnd, buf, para1, value1); extractEnd = extractTemp; if(extractEnd == 0xffff) { /*说明只传来了一对参数,如led1=1或led2=2或led3=3*/ switch(value1[0]) { case '1':{ value1[0]=1;strcpy(para1,para1); value2[0]=0;strcpy(para2,"0"); value3[0]=0;strcpy(para3,"0"); break; } case '2': { value2[0]=2;strcpy(para2,para1); value1[0]=0;strcpy(para1,"0"); value3[0]=0;strcpy(para3,"0"); break; } case '3': { value3[0]=3;strcpy(para3,para1); value1[0]=0;strcpy(para1,"0"); value2[0]=0;strcpy(para2,"0"); break; } } break; } extractTemp = paraExtract(extractEnd, buf, para2, value2); extractEnd = extractTemp; if(extractEnd == 0xffff) { /*说明只传来了两对参数,如led1=1&led2=2或led2=2&led3=3或者led1=1&led3=3*/ switch(value1[0]) { case '1': { switch(value2[0]) { case '2':{value2[0]=2;strcpy(para2,para2);break;} case '3':{ value3[0]=3;strcpy(para3,para2); value2[0]=0;strcpy(para2,"0"); break; } } break; } case '2': { value3[0]=3;strcpy(para3,para2); value2[0]=2;strcpy(para2,para1); value1[0]=0;strcpy(para1,"0"); break; } } break; } extractTemp = paraExtract(extractEnd, buf, para3, value3); extractEnd = extractTemp; break; } //end while }//end if /*下面这部分通过上面解析出来的信息,调用led驱动程序,控制led灯*/ int fd; fd = open("/dev/leds", 0);//打开led设备 if (fd < 0) { perror("open device /dev/leds"); exit(1); } if(value1[0]==0) { ioctl(fd, 0, 0); } else { ioctl(fd, 1, 0); } if(value2[0]==0) { ioctl(fd, 0, 1); } else { ioctl(fd, 1, 1); } if(value3[0]==0) { ioctl(fd, 0, 2); } else { ioctl(fd, 1, 2); } /*下面这部分发送HTTP相应到客户端*/ printf("Content-type: text/html\n\n"); printf("\n"); printf("<h1> 简单LED测试(CGI实现)</h1>\n"); printf("\n"); printf("LED设置已经提交\n

"); printf("返回上一页\n

"); //printf("led1=%s\n

",value1); //printf("led2=%s\n

",value2); //printf("led3=%s\n

",value3); printf("\n"); printf("\n"); fflush(stdout); return 0; } 至此CGI程序已经编好了,然后对它进行交叉编译后,通过NFS下载到开发板的/root/web/cgi-bin目录下,下面就可以通过网页控制开发板的LED灯了。 效果如下: 点击提交按钮后,网页变为: 注意:如果网页提示出错,那需要修改CGI 程序的权限。 简单LED控制(JavaScript实现) 本实验用JavaScript技术实现了控制LED灯,注意这个实例和上个实例的区别,先看以下效果: 按下led1按钮,网页变为: 注意提交前后网页的变化。提交后网页还是以前的网页,这点和前面的实验不同,前面提交之后,显示的是服务器传过来的确认信息。 本手册提供了两种实现方法,可根据具体情况选取不同方法。 学习本实验之前,首先应该学习一下JavaScript语言。JavaScript是客户端的脚本语言,在Web编程中,它的主要应用是校验表单数据和创建动态的XHTML文档。 注意:做实验前应先修改网页代码中的IP地址为开发板的IP地址,黑色部分。 下面是控制LED灯的网页代码content-4.html: LED测试

简单LED测试(JavaScript实现)

工作流程大概是: ⑴首先客户端浏览器检查是否有按钮按下,当有按钮按下时,触发事件onclick,调用相应的addPara()函数。 ⑵在addPara()函数中调用addURLParamGet()函数,按照规则添加相应的参数到URL后面。 ⑶接下来创建 XMLHttpRequest 对象,通过以下代码 xmlhttp.open("GET",url,false); xmlhttp.send(null); 建立和服务器的连接,并把url传送到服务器端进行处理解析。 客户端浏览器 Web服务器 CGI程序 其它程序
/
本文档为【通过Web浏览器控制开发板硬件】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索