gpio_request
快門驅(qū)動(dòng)芯片ms8837 輸入信號(hào)是兩個(gè)GPIO,最開始是在camera 驅(qū)動(dòng)中調(diào)用 gpio_request() 申請(qǐng)GPIO,當(dāng) open/close camera 的時(shí)候就可以調(diào)用 gpio_direction_output() 來控制快門的開、關(guān)。
在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>;
};
在camera 驅(qū)動(dòng)中調(diào)用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() */
這樣在open/close camera 的時(shí)間是可以正常調(diào)用的,但后續(xù)的開發(fā)遇到了問題,原來是想通過camera 的 feature control 來發(fā)送快門開、關(guān)指令,但是發(fā)現(xiàn)非常復(fù)雜,快門指令是要結(jié)合3A處理的,就先放棄了,轉(zhuǎn)而用 ioctl 的方法去實(shí)現(xiàn)。
SYSFS
看其它帖子,控制GPIO最簡單的方法是通過SYSFS:
make menuconfig
因?yàn)闆]有 /sys/class/gpio 路徑,需要通過make menuconfig,將GPIO 映射到sysfs 文件系統(tǒng)中。
在kernel-4.4/ 下 make menuconfig 失敗及解決方法:
配置后 out/.config 文件中CONFIG_GPIO_SYSFS is not set,可見并未生效;直接在kernel-4.4/arch/arm64/configs/*_defconfig 中加入:
CONFIG_GPIO_SYSFS=y
這下有 /dev/class/gpio 路徑了。
export
執(zhí)行第二步:echo 163 > export 時(shí)未生成gpio163 路徑,同時(shí)kernel log 報(bào)錯(cuò):
export_store: invalid GPIO 163
有可能是因?yàn)镚PIO 被占用了的原因,因?yàn)檫@個(gè)方法也不方便app去調(diào)用,所以暫時(shí)放棄。
GPIO驅(qū)動(dòng)
編譯
在kernel-4.4/drivers/gpio/ 下添加GPIO 驅(qū)動(dòng)文件 gpio-ms8837.c,同時(shí)修改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.
+obj-$(CONFIG_GPIO_MS8837) += gpio-ms8837.o
注:Kconfig 也要改,只改Makefile 不會(huì)編譯gpio-ms8837.o
驅(qū)動(dòng)分析
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;
}
標(biāo)記1 處的device_create 負(fù)責(zé)在 /dev/ 下生成設(shè)備文件,屏蔽掉,設(shè)備文件就沒有創(chuàng)建。
那么設(shè)備文件是如何創(chuàng)建的呢?
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().(用于創(chuàng)建一個(gè)class 結(jié)構(gòu)體指針,用于device_create() 的調(diào)用。)class_create()調(diào)用后,會(huì)在/sys/class 下創(chuàng)建設(shè)備目錄。本文是創(chuàng)建了 /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.(該函數(shù)可用于字符型設(shè)備類。用于在sysfs 中創(chuàng)建device 結(jié)構(gòu)體,并注冊(cè)到特定的class 中。)device_create()調(diào)用后會(huì)在 /dev/下建立設(shè)備節(jié)點(diǎn),本文是/dev/shutter。這樣用戶層就可以 去訪問設(shè)備了。class 與 device 通過 /sys/devices/virtual/shutter/shutter 關(guān)聯(lián)。
剩下的就是 file_operations 了,read/write/ioctl 等,根據(jù)需求去實(shí)現(xiàn)。
static const struct file_operations gpio_ops={
.owner = THIS_MODULE,
.open = gpio_ms8837_open,
.unlocked_ioctl = gpio_ms8837_ioctl
};
補(bǔ)充:也可以通過mknod 指令去創(chuàng)建設(shè)備節(jié)點(diǎn)
mknod
[OPTION]… NAME TYPE [MAJOR MINOR]
文章來源:http://www.zghlxwxcb.cn/news/detail-769175.html
參考文檔:
https://cloud.tencent.com/developer/article/1599571
https://zhuanlan.zhihu.com/p/442079581
http://blog.chinaunix.net/uid-22666248-id-3052861.html文章來源地址http://www.zghlxwxcb.cn/news/detail-769175.html
到了這里,關(guān)于【學(xué)習(xí)筆記:GPIO驅(qū)動(dòng)開發(fā)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!