当前位置:   article > 正文

【学习笔记:GPIO驱动开发】_export_store: invalid gpio 110

export_store: invalid gpio 110

gpio_request

快门驱动芯片ms8837 输入信号是两个GPIO,最开始是在camera 驱动中调用 gpio_request() 申请GPIO,当 open/close camera 的时候就可以调用 gpio_direction_output() 来控制快门的开、关。
在dts 中加入引脚配置:

kd_camera_hw1:kd_camera_hw1@1a040000 {
		compatible = "mediatek,imgsensor";
		cam2_vcama_d_ext = <&pio 162 0x0>; 
		cam_shutter_in1 = <&pio 163 0x0>;
		cam_shutter_in2 = <&pio 164 0x0>;
	};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在camera 驱动中调用gpio_request() 去控制GPIO:

UINT32 XXX_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
{
	/* To Do : Check Sensor status here */
	int ret;
	struct device_node * node;
	SENSORDB("%s",__func__);
	if (pfFunc!=NULL)
		*pfFunc=&SensorFuncXXX;
	node = of_find_compatible_node(NULL, NULL, "mediatek,imgsensor");
	if (!node) {
		printk(" Get cust camera node failed!\n");
		return -ENODEV;
	}
	cam_shutter_in1  = of_get_named_gpio(node, "cam_shutter_in1", 0);
	ret = gpio_request(cam_shutter_in1,"cam_shutter_in1");
	if (ret) {
		printk("error: cam_shutter_in1 gpio_request\n");
		return -1;
	}
			
	ret = gpio_direction_output(cam_shutter_in1, 1);
	if (ret) {
		printk("error %s : cam_shutter_in1  gpio_direction_output failed\n",__func__);
		ret = -1;
	}
	cam_shutter_in2  = of_get_named_gpio(node, "cam_shutter_in2", 0);
	ret = gpio_request(cam_shutter_in2,"cam_shutter_in2");
	if (ret) {
		printk("error: cam_shutter_in2 gpio_request\n");
		return -1;
	}
		
	ret = gpio_direction_output(cam_shutter_in2, 0);
	if (ret) {
		printk("error %s : cam_shutter_in2  gpio_direction_output failed\n",__func__);
		ret = -1;
	}
	printk("cam_shutter_in1:%d, cam_shutter_in2:%d\n", cam_shutter_in1, cam_shutter_in2);
	return ERROR_NONE;
} /* SensorInit() */

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

这样在open/close camera 的时间是可以正常调用的,但后续的开发遇到了问题,原来是想通过camera 的 feature control 来发送快门开、关指令,但是发现非常复杂,快门指令是要结合3A处理的,就先放弃了,转而用 ioctl 的方法去实现。

SYSFS

看其它帖子,控制GPIO最简单的方法是通过SYSFS:
在这里插入图片描述

make menuconfig

因为没有 /sys/class/gpio 路径,需要通过make menuconfig,将GPIO 映射到sysfs 文件系统中。
在kernel-4.4/ 下 make menuconfig 失败及解决方法:
在这里插入图片描述
配置后 out/.config 文件中CONFIG_GPIO_SYSFS is not set,可见并未生效;直接在kernel-4.4/arch/arm64/configs/*_defconfig 中加入:

CONFIG_GPIO_SYSFS=y
  • 1

这下有 /dev/class/gpio 路径了。

export

执行第二步:echo 163 > export 时未生成gpio163 路径,同时kernel log 报错:
export_store: invalid GPIO 163
有可能是因为GPIO 被占用了的原因,因为这个方法也不方便app去调用,所以暂时放弃。

GPIO驱动

编译

在kernel-4.4/drivers/gpio/ 下添加GPIO 驱动文件 gpio-ms8837.c,同时修改kernel-4.4/drivers/gpio/ 下的Kconfig 和 Makefile:

+config GPIO_MS8837
+       tristate "MS8837 GPIOs"
+       help
+         This option enables support for on-chip GPIO found
+         on MS8837.
  • 1
  • 2
  • 3
  • 4
  • 5
+obj-$(CONFIG_GPIO_MS8837)      += gpio-ms8837.o
  • 1

注:Kconfig 也要改,只改Makefile 不会编译gpio-ms8837.o

驱动分析

static int __init gpio_shutter_init(void)
{
    int devno;
    dev_t num_dev;

    printk("%s is called. \n", __func__);

    alloc_chrdev_region(&num_dev, gpio_minor, 1, MYGPIO_NAME);

    gpio_major = MAJOR(num_dev);
    printk("gpio_major = %d. \n", gpio_major);

    gpio_class = class_create(THIS_MODULE, MYGPIO_NAME);

    devno = MKDEV(gpio_major, gpio_minor);

    cdev_init(&gpio_cdev, &gpio_ops);

    cdev_add(&gpio_cdev, devno, 1);

    device_create(gpio_class, NULL, devno, NULL, MYGPIO_NAME);//1

#ifdef MYGPIO_HW_ENABLE
    gpio_shutter_hw_init();
#endif

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

标记1 处的device_create 负责在 /dev/ 下生成设备文件,屏蔽掉,设备文件就没有创建。
那么设备文件是如何创建的呢?
class_create() 源码:
kernel-4.4\drivers\base\class.c
device_create() 源码:
kernel-4.4\drivers\base\core.c

class_create()
This is used to create a struct class pointer that can then be used in calls to device_create().(用于创建一个class 结构体指针,用于device_create() 的调用。)class_create()调用后,会在/sys/class 下创建设备目录。本文是创建了 /sys/class/shutter 。
device_create()
This function can be used by char device classes. A struct device will be created in sysfs, registered to the specified class.(该函数可用于字符型设备类。用于在sysfs 中创建device 结构体,并注册到特定的class 中。)device_create()调用后会在 /dev/下建立设备节点,本文是/dev/shutter。这样用户层就可以 去访问设备了。class 与 device 通过 /sys/devices/virtual/shutter/shutter 关联。

在这里插入图片描述
剩下的就是 file_operations 了,read/write/ioctl 等,根据需求去实现。

static const struct file_operations gpio_ops={
    .owner = THIS_MODULE,
    .open  = gpio_ms8837_open,
    .unlocked_ioctl = gpio_ms8837_ioctl
};
  • 1
  • 2
  • 3
  • 4
  • 5

补充:也可以通过mknod 指令去创建设备节点
mknod
[OPTION]… NAME TYPE [MAJOR MINOR]
![](https://img-blog.csdnimg.cn/direct/f1367c380cda45c9a4c64f1ec63878a1.png
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7830cd5340b04473bfb282b20bd0c2ea.png

参考文档:
https://cloud.tencent.com/developer/article/1599571
https://zhuanlan.zhihu.com/p/442079581
http://blog.chinaunix.net/uid-22666248-id-3052861.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/365191
推荐阅读
相关标签
  

闽ICP备14008679号