之前提到过的那个开发板监控的事儿,做了一些了,目前在翼辉信息公司的开发人员的帮助下,把数码显像管的部分实现了,然后这几天在研究怎么搞定GPIO的部分。
需求简单来讲是这样的:
的地方就是,A程序相当于是别人已经写好的程序(改不了),B程序才是我要写的监控程序,也就是说想通过A程序与B程序进程间通信的方法来实现已经不太可能了。
GPIO部分跟数码显像管相比有个特别不一样的地方就是,他们写的数码显像管的驱动实现是把他弄成了一个普通的块子符设备,然后我可以像操作普通的块子符设备一样打开(可以多次打开,也就是说在A程序使用LED时,B程序也可以打开LED进行读操作),但是GPIO的使用上面,据SylixOS应用开发手册上来讲,是不能同时用gpiofd函数open同一个GPIO编号的,也就是说在两个进程里面打开同一个GPIO不行。
第一种我自己想的思路是去改BSP的GPIO驱动,后来发现实现起来太困难了,还要用内核GPIO管理结构体里面的保留的字段,而且还要重新刷一遍板子系统重新部署,想了想放弃了。
后面又去咨询了一下翼辉的官方(这里不得不说他们回复还是很及时,有个群,里面系统的作者也在里面解答问题)
给我提供了一个正常的思路(也是官方开发人员提供给我的思路)是这样:写一个内核模块,调用内核的这个API函数进行监控:
/********************************************************************************************************* ** 函数名称: API_GpioGetValue ** 功能描述: 获取指定 GPIO 的值 ** 输 入 : uiGpio GPIO 号 ** 输 出 : GPIO 当前电平状态 1: 高电平 0: 低电平 ** 全局变量: ** 调用模块: ** 注 意 : 此函数不做任何参数有效性判断, 所以用户必须保证 uiGpio 已经请求成功, 方向与其他参数设置正确. API 函数 *********************************************************************************************************/ LW_API INT API_GpioGetValue (UINT uiGpio) { PLW_GPIO_DESC pgdesc; PLW_GPIO_CHIP pgchip; pgdesc = GPIO_TO_DESC(uiGpio); /* 不做任何检查, 加快速度 */ pgchip = pgdesc->GD_pgcChip; return (pgchip->GC_pfuncGet(pgchip, GPIO_CHIP_HWGPIO(pgdesc))); }
然后在这个内核模块里面虚拟化一个GPIO的proc,把读到的数据存到这个proc里,然后B程序再用读proc程序的方法去读到GPIO的状态数据,再进行后续处理。
然而SylixOS的应用开发手册上面没有proc文件的创建以及读写示例程序,我去看了sylixosbase工程的libsylixos/SylixOS/fs/procFs/procPower/procPower.c,想参考下写一个proc,但是看了看跟linux下面创建以及读写proc的差距有点大,要先设计填充好几个结构体,才能使用一个API_ProcFsMakeNode注册一个proc文件并关联读写函数。这个看了看比较蛋疼,主要问题还是对SylixOS不太了解,估计实际流程走下来跟Linux创建并关联读写函数的方式应该差不多,感兴趣的同志们可以继续研究下。
这个时候我突发奇想,虽然API函数说是只能给内核使用,但是如果我在应用层直接使用会怎么样呢?于是我写了个测试的程序, 引用了API_GpioGetValue所在的头文件(这个程序可以看成B程序):
#include <stdio.h> #include <system/device/gpio/gpioLib.h> #define LED1_GPIO_NUM 24 #define LED2_GPIO_NUM 30 #define LED3_GPIO_NUM 26 #define LED4_GPIO_NUM 27 #define LED5_GPIO_NUM 37 #define LED6_GPIO_NUM 32 #define LED7_GPIO_NUM 29 int main (int argc, char **argv) { int uiValue; while(1){ uiValue = API_GpioGetValue(LED1_GPIO_NUM); printf("gpio LED1:%d\n",uiValue); usleep(400 * 1000);///要保证比下面那个程序闪烁频率快 } return (0); }然后再写一个SylixOS下标准的gpio操作led灯的程序(这个程序可以看成A程序):
#include <sys/gpiofd.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> /****************************************************************************** ** 函数名称: main ** 功能描述: 程序主函数 ******************************************************************************/ int main (int argc, char *argv[]) { int led_num = 24; int i; int fd; /* * 打开 GPIO 文件 */ fd = gpiofd(led_num, O_WRONLY, GPIO_FLAG_OUT_INIT_LOW); if (fd < 0) { printf("failed to open gpio %d\n", led_num); return (-1); } for (i = 0; i < 60; i++) { /* * 对 LED 进行闪烁,每次高低电平操作前,使用usleep进行延时500ms。 */ gpiofd_write(fd, 0); usleep(500 * 1000); gpiofd_write(fd, 1); usleep(500 * 1000); } close(fd); /* 关闭设备 */ return (0); }
编译通过,没有问题,上传部署,也没有问题。
然后把B程序跑在后台,前台跑A程序。这个时候发现,板子的LED灯正常闪烁(A控制的方式),而且这种十分不规范的方式居然是可以读到GPIO的状态的,B是可以输出读到的GPIO电平高低值,而且基本上也是正确的(当然时间差什么的可以忽略)。
这种方式,肯定是不合规范的,而且可能产生未知的bug,但是我们都知道,产生bug一般是因为同时读写,我这里单纯只是读的话,我个人认为不会有什么问题,但是可能以后系统升级了,这种代码就无效作废了。不过暂时就依靠这种不合规范的方式先实现功能吧!