|
[BB方案]第四辑全月刊——php服务器+pruss初尝甜头+与pruss交换数据+php管道通信
[复制链接]
本帖最后由 sjtitr 于 2014-6-6 00:18 编辑
答应管理员本周内发新帖,就是要说到做到。
——楼主 |
不做上辑回顾了。不只是因为上辑太遥远,实在想不起来做了什么;更是因为,这一辑是全新的开始,与前文无关,甚至,展开了一个全新的思路,不需要前文的技术铺垫了。
要不然也是计划本周整理一下的。忽悠一下,一个月过去了,上次也就是第三辑,已经过去一个月还多了。这一个月真的很忙很忙,工作上不能怠慢,家里琐事一堆。BBB的事尽管没有在桌面上,但是一直在心里,不断的挤出时间,沉淀一些知识。
纵然不回顾,也记得前面花了一个月的时间,研究BBB的内核驱动,为了利用驱动来实现红外遥控器功能。按照计划,第二个月,也就是刚刚过去的一个月,需要研究PHP相关的内容,以实现PHP和驱动的互动。如果你有耐心读完本文,你会知道,计划变了——本月没有花那么多时间研究PHP,最后的方案也不再使用内核驱动。究竟过去这一个月楼主都研究了些什么,且听我一一道来……鉴于现在还是挺忙的,大家的时间也宝贵,之后咱们就挑干的长话短说啦。
【一、PHP服务器的搭建】
@chenzhufly 老师还是很给力的,好多文章都不是白给的,仔细阅读,能节省不少青春岁月。
在beaglebone black上安装lighttp
仅仅是花了一会儿的时间,服务器就建立完毕,接下来是php的学习,不得不花点时间,学学网页开发吧。可以简单的编一些代码用于测试什么的。我还是喜欢到 PHP 教程去学习,
只需两天,在服务器上建立自己的测试程序(php网页)就得心应手了。
如何用PHP页面控制小灯?我们来实现一个页面吧……
- <html>
- <head>
- <title>Test Page</title>
- </head>
- <body>
- <?php
- $led = $_REQUEST['led'];
- print("Hello World!");
- echo nl2br("\n");
- print("Led : ");
- echo $led;
- echo nl2br("\n");
- print("sjtitr");
- echo nl2br("\n");
- if($led == 1)
- {
- $file = fopen("/sys/class/gpio/gpio44/value","w");
- if($file)
- {
- fputs($file, "1");
- fclose($file);
- }
- ?>
- <a href="test.php?led=0">LED=0</a>
- <?php
- }
- else
- {
- $file = fopen("/sys/class/gpio/gpio44/value","w");
- if($file)
- {
- fputs($file, "0");
- fclose($file);
- }
- ?>
- <a href="test.php?led=1">LED=1</a>
- <?php
- }
- ?><br>
- </body>
- </html>
复制代码
使用页面以前呢,先通过命令行打开端口的设定。
- echo 44 > /sys/class/gpio/export
- echo out > /sys/class/gpio/gpio44/direction
- echo 1 > /sys/class/gpio/gpio44/value
复制代码
可是PHP如何与内核驱动结合起来呢?另外内核驱动控制小灯,明显频率不稳定,毕竟也参与系统调度中来了,那么如何获取精准的时序控制呢?那楼主第二周就来研究这个问题吧。
【二、pruss初次探秘】
不得不说,之前根本没有关注过BBB的这部分硬件内容。要不是我追求时序上的完美,几乎AM335x的这一利刃都要被我无视了。幸亏楼主孜孜不倦的搜索,终于被我给发现了——这是一个 AM335x等芯片上自带的,独立于ARM CPU运行的子系统。其时钟频率为200MHz,可以直接控制特定的IO口,可以达到非常高的实时性要求。一般两种情况需要用到它:一是linux系统的实时性不满足要求的时候;二是芯片的功能模块不够用的时候(比如你想要10个UART,但芯片上只有6个,那你可以用它再创造4个)。采自本论坛原文: AM335x的PRUSSv2简介与使用
同样的道理,参照该文,建立pruss的开发环境。最后可以操纵pruss对端口进行控制。
于是把之前做过的控制小灯的实验,搬到pru中来进行,还是那个引脚,还是那样连接……
楼主比较懒,所以还是先用命令行把端口设置妥当:
- echo 44 > /sys/class/gpio/export
- echo out > /sys/class/gpio/gpio44/direction
- echo 1 > /sys/class/gpio/gpio44/value
复制代码
之后pru只需要控制输出值的0、1就可以了。
- //prucode.p
- .origin 0
- .entrypoint START
- //Refer to this mapping in the file - prussdrvincludepruss_intc_mapping.h
- #define PRU0_ARM_INTERRUPT 19
- #define CONST_PRUCFG C4
- //Refer to AM335X Technical Reference Manual & BBB SRM
- #define GPIO1 0x4804c000
- #define GPIO_CLEARDATAOUT 0x190
- #define GPIO_SETDATAOUT 0x194
- START:
- // Enable OCP master port
- LBCO r0, CONST_PRUCFG, 4, 4
- CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port
- SBCO r0, CONST_PRUCFG, 4, 4
- MOV r1, 3 // loop 3 times
- LOOP0:
- MOV r2, 1<<12
- MOV r3, GPIO1 | GPIO_SETDATAOUT
- SBBO r2, r3, 0, 4
- MOV r0, 20000000
- DEL1:
- SUB r0, r0, 1
- QBNE DEL1, r0, 0
- MOV r2, 1<<12
- MOV r3, GPIO1 | GPIO_CLEARDATAOUT
- SBBO r2, r3, 0, 4
- MOV r0, 20000000
- DEL2:
- SUB r0, r0, 1
- QBNE DEL2, r0, 0
- SUB r1, r1, 1
- QBNE LOOP0, r1, 0
- // Send notification to Host for program completion
- MOV r31.b0, PRU0_ARM_INTERRUPT+16
- // Halt the processor
- HALT
复制代码
真不骗人,我敢贴出代码,就是因为这代码我改过了,即便是那么一点点修改,也要翻看各种手册才得以确认。
就是这段代码,参考原文编译加载执行,就能看到我们前面一辑里描述的小灯一闪一闪亮3次啦,时间上嘛,相当精准。
但是要实现利用这代码来控制实现红外线遥控器波形,恐怕还得挨些累呀。所以必须要继续研究。
【三、与pruss交换数据】
想用pruss控制波形,第一件麻烦事就是要发送的数据由C语言程序传递到pru程序。在这一研究过程中,了解到的东西远不止这几个数据。简单说,其实pru使用的空间(无论数据还是代码),都存在在我们的flat内存空间上。所以只要找对地方,把数据写入。
- //mytest.c
- #include <stdio.h>
- #include <prussdrv.h>
- #include <pruss_intc_mapping.h>
- #define PRU_NUM 0
- int main (void)
- {
- unsigned int ret;
- tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
- prussdrv_init ();//Initialize the PRU
- if (prussdrv_open(PRU_EVTOUT_0))//Open PRU Interrupt
- {
- printf("prussdrv_open open failed");
- return (-1);
- }
- prussdrv_pruintc_init(&pruss_intc_initdata);
- {
- unsigned int v = 10;
- prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0, &v, 4);
- }
- prussdrv_exec_program (PRU_NUM, "./prucode.bin");//Execute example on PRU
- prussdrv_pru_wait_event (PRU_EVTOUT_0);//Waiting for this instruction: MOV r31.b0, PRU0_ARM_INTERRUPT+16
- prussdrv_pru_clear_event (PRU0_ARM_INTERRUPT,0);
- prussdrv_pru_disable (PRU_NUM);//Disable PRU and close memory mapping
- prussdrv_exit ();
- return(0);
- }
复制代码
注意到其中的
- {
- unsigned int v = 10;
- prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0, &v, 4);
- }
复制代码
这就是向pru单元写入数据(事实上传程序进去,也是类似的就这样一个实质上的数据copy)。
而我们在pru中,则先对数据进行一个简单分析——再确定闪灯的次数。
- //prucode.p
- .origin 0
- .entrypoint START
- //Refer to this mapping in the file - prussdrvincludepruss_intc_mapping.h
- #define PRU0_ARM_INTERRUPT 19
- #define CONST_PRUCFG C4
- //Refer to AM335X Technical Reference Manual & BBB SRM
- #define GPIO1 0x4804c000
- #define GPIO_CLEARDATAOUT 0x190
- #define GPIO_SETDATAOUT 0x194
- START:
- // Enable OCP master port
- LBCO r0, CONST_PRUCFG, 4, 4
- CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port
- SBCO r0, CONST_PRUCFG, 4, 4
- //MOV r1, 3 // loop 3 times
- MOV r2, 0
- LBBO r1, r2, 0, 4
- LOOP0:
- MOV r2, 1<<12
- MOV r3, GPIO1 | GPIO_SETDATAOUT
- SBBO r2, r3, 0, 4
- MOV r0, 20000000
- DEL1:
- SUB r0, r0, 1
- QBNE DEL1, r0, 0
- MOV r2, 1<<12
- MOV r3, GPIO1 | GPIO_CLEARDATAOUT
- SBBO r2, r3, 0, 4
- MOV r0, 20000000
- DEL2:
- SUB r0, r0, 1
- QBNE DEL2, r0, 0
- SUB r1, r1, 1
- QBNE LOOP0, r1, 0
- // Send notification to Host for program completion
- MOV r31.b0, PRU0_ARM_INTERRUPT+16
- // Halt the processor
- HALT
复制代码
这个pru的成功,令楼主很是兴奋。不过,之后的,如何能把pru结合到内核驱动里去,却另楼主很是挠头。好在,两天后,楼主想通了。
控制红外线的时序,交给pru就好啦,根本没必要再加一个内核驱动了。剩下的事,无非就是,应用程序从php获取数据,然后传递给pru,再让pru执行生成红外线时序的代码咯。
于是楼主的设计方案就变了。
【四、PHP通过命名管道和应用程序交换数据】
最后一件事呢,无疑就是PHP怎样把数据交给到应用程序里了。这里不知怎的,楼主是很自然的就想到用命名管道。于是针对这个内容的调查研究很快就展开了。
学习过程省略,首先实现一个监听程序:这里做了个很简单的协议啦。
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define FIFO "/tmp/irfifo"
- int main(int argc, char** argv)
- {
- char buf[64];
- int fd;
- int nread;
- if((mkfifo(FIFO, O_CREAT|O_EXCL)<0) && (errno!=EEXIST))
- {
- printf("cannot create fifo\n");
- }
- fd = open(FIFO, O_RDONLY);
- if(fd==-1)
- {
- printf("cannot open fifo\n");
- exit(1);
- }
- while(1)
- {
- int i = 0;
- memset(buf, 0, sizeof(buf));
- read(fd, buf, 1);
- if(buf[0]!=0x5A)
- {
- // printf("%X,", buf[0]);
- continue;
- }
- read(fd, buf, 1);
- if(buf[0] == 0)
- {
- break;
- }
- read(fd, &buf[1], buf[0]);
- printf("%d: ", buf[0]);
- while(i < buf[0])
- {
- i++;
- printf("%X,",buf[i]);
- }
- printf("\n");
- }
- unlink(FIFO);
- exit(0);
- }
复制代码
其次,不要着急PHP,再写个工作程序给监听程序送些试验数据:很简单,执行时候的第一个参数字符串和它的长度作为内容传递给pipe
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define FIFO "/tmp/irfifo"
- int main(int argc, char** argv)
- {
- char buf[64];
- int fd;
- int nread;
- fd = open(FIFO, O_WRONLY);
- if(fd==-1)
- {
- printf("cannot open fifo\n");
- exit(1);
- }
- buf[0] = 0x5A;
- if(argc <=1)
- {
- buf[1] = 0;
- }
- else
- {
- buf[1] = strlen(argv[1]);
- memcpy(&buf[2], argv[1], buf[1]);
- }
- if(write(fd, &buf[0], buf[1]+2)==-1)
- {
- printf("error\n");
- }
- close(fd);
- exit(0);
- }
复制代码
这不是完美程序。完美还有很远的路要走。
经过试验,确信监听程序可用了。太好了,接下来我们才准备PHP。
这下可遇到麻烦了,php里面写文件全是用字符串么?唉,对PHP还是不够了解呀……继续学!
于是了解到如果利用php处理字节流数据……很好很强大……pack函数。
随后,终于形成了php的测试页面,可以把字节流传递给pipe文件。
- <html>
- <head>
- <title>Test Pipe Page</title>
- </head>
- <body>
- <?php
- $str = $_REQUEST['str'];
- $fp = @fopen("////tmp//irfifo", 'w');
- echo $fp;
- echo nl2br("\n");
- $num = 0x5a;
- $data = pack("H2", "5a");
- echo @fwrite($fp, $data);
- echo nl2br("\n");
- $data = pack("C1", strlen($str)/2);
- echo @fwrite($fp, $data);//D′
- echo nl2br("\n");
- $data = pack("H*", $str);
- echo @fwrite($fp,$data);//D′
- echo nl2br("\n");
- fclose($fp);
- echo nl2br("\n");
- print("Hello World!");
- echo nl2br("\n");
- print("sjtitr");
- echo nl2br("\n");
- ?>
- </body>
- </html>
复制代码
OK,第二个月的内容可以暂时松口气啦。
【月底总结】
虽然是月底总结,可是到我发出来,也晚了有一个星期,所以周末的时候,会直接发出第三个月第一周的作业内容:最终方案构想设计……
其实可以说走了不少弯路,不过路上都是知识,我很担心也很满足。担心的是怕方案烂尾,这可不是我的一贯作风啊……满足的是,事已至此,这一段时间,确实自己也能感觉得到自己的长进呢。
其实这第二个月的内容最令我感到动荡不安了,恍惚中学过来,发现似乎离成功是越走越近的。至少从目前来看,对于我付出的时间和精力,都是已然够本了——如果读到这篇文章的童鞋能够从中受益,那我要说,咱们赚了!
|
|