《嵌入式驱动(六):pinctrl子系统和gpio子系统驱动》
一、Linux驱动分层思想

1.设备与驱动分离思想
和设备相关的信息放到设备树里,驱动里面只写对于设备的操作方法
2.驱动分层思想
把相同的操作提出来,构建子系统,子系统可以完成这些通用的操作(GPIO,引脚)
二、pinctrl子系统(linux内核中自带该系统)
我们通过设备树来使用pinctrl子系统。pinctrl子系统中有2个概念:
pin controller(一种引脚的定义和实现):它对应IOMUX来复用引脚
client device(使用某种引脚定义方向):pinctrl子系统的客户,即使用pinctrl系统的设备。
在imx6ull-alientek-emmc.dts文件中iomuxc节点中定义controller引脚配置
pinctrl_putekey: putekey {
fsl,pins = <MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0xf0b0>;
};
在对应的putekey节点中引用该方案
putekey {
#address-cells = <1>;
#size-cells = <1>;
compatible = "pute-key";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_putekey>;
reg = <0x209C004 0x4
0x209C000 0x4>;
status = "okay";
};
三、gpio子系统
在设备中指定节点使用的GPIO引脚编号
1. 在设备中指定节点使用的GPIO引脚编号,格式如下:
putekey {
#address-cells = <1>;
#size-cells = <1>;
compatible = "pute-key";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_putekey>;
gpio-key = <&gpio1 18 GPIO_ACTIVE_LOW>;
status = "okay";
};
在putekey节点里面修改
2. 在驱动中编写代码
2.1.通过of_get_named_gpio从设备树节点中解析并获取指定GPIO硬件编号
2.2.通过gpio_request申请GPIO资源
2.3.通过gpio_direction_input/output设置GPIO的方向
2.4.通过gpio_get_value 读取输入引脚电平
gpio_set_value设置输出引脚电平
2.5.释放GPIO,gpio_free()
四、代码
以key为例
pinctrl子系统
pinctrl_putekey: putekey {
fsl,pins = <MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0XF0B0>;
};
gpio子系统
putekey {
#address-cells = <1>;
#size-cells = <1>;
compatible = "pute-key";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_putekey>;
gpio-key = <&gpio1 18 GPIO_ACTIVE_LOW>;
status = "okay";
};
key_app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int fd = 0;
int stat = 0;
fd = open("/dev/misc_key", O_RDWR);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
while (1)
{
read(fd, &stat, sizeof(stat));
printf("stat = %d\n", stat);
}
close(fd);
return 0;
}
Makefile
#模块名
modulename := key_app
#编译工具链
CC := arm-linux-gnueabihf-gcc
all:
$(CC) $(modulename).c -o $(modulename)
cp $(modulename) ~/nfs/rootfs
.PHONY:
clean:
rm $(modulename)
distclean:
rm $(modulename)
rm ~/nfs/rootfs/$(modulename)
key_drv.c
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
static struct device_node *pkeynode = NULL;
static int gpiokey = 0;
static ssize_t key_read(struct file *fp, char __user *puser, size_t n, loff_t *off)
{
int status = 0;
unsigned long nret = 0;
if (gpio_get_value(gpiokey)) {
status = 0;
} else {
status = 1;
}
nret = copy_to_user(puser, &status, sizeof(status));
if (nret) {
pr_info("copy_to_user failed\n");
return -1;
}
return nret;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.read = key_read,
};
static struct miscdevice misc_key = {
.minor = MISC_DYNAMIC_MINOR,
.name = "misc_key",
.fops = &fops,
};
static __init int key_drv_init(void)
{
int ret = 0;
ret = misc_register(&misc_key);
if (ret) {
pr_info("misc_register failed\n");
return -1;
}
pkeynode = of_find_node_by_path("/putekey");
if (NULL == pkeynode) {
pr_info("of_find_node_by_path failed\n");
return -1;
}
gpiokey = of_get_named_gpio(pkeynode, "gpio-key", 0);
if (gpiokey < 0) {
pr_info("of_get_named_gpio failed\n");
return -1;
}
ret = gpio_request(gpiokey, "pute-key-gpio");
if (ret) {
pr_info("gpio_request failed\n");
return -1;
}
ret = gpio_direction_input(gpiokey);
if (ret) {
pr_info("gpio_direction_input failed\n");
return -1;
}
pr_info("key_drv_init success\n");
return 0;
}
static __exit void key_drv_exit(void)
{
int ret = 0;
gpio_free(gpiokey);
ret = misc_deregister(&misc_key);
if (ret) {
pr_info("misc_deregister failed\n");
return;
}
pr_info("key_drv_exit success\n");
return;
}
module_init(key_drv_init);
module_exit(key_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("pute");
Makefile
#模块名
modulename := key_drv
#内核路径
kerdir := /home/linux/imx6ull/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
#加入内核编译中
obj-m += $(modulename).o
#当前路径
pwd := $(shell pwd)
all:
make -C $(kerdir) modules M=$(pwd)
cp $(modulename).ko ~/nfs/rootfs
.PHONY:
clean:
make -C $(kerdir) modules M=$(pwd) clean
distclean:
make -C $(kerdir) modules M=$(pwd) clean
rm ~/nfs/rootfs/$(modulename).ko
Makefile
#模块名
modulename := key
all:
make -C $(modulename)_drv
make -C $(modulename)_app
.PHONY:
distclean:
make -C $(modulename)_drv distclean
make -C $(modulename)_app distclean
clean:
make -C $(modulename)_drv clean
make -C $(modulename)_app clean
更多推荐



所有评论(0)