gpio框架
用户层
---------------------------------------------------------------------------------------------------------------------------------
驱动层:调用核心层提供的接口,驱动开发
内核层:屏蔽底层细节,为上一层提供接口;由内核工程师负责
硬件层:厂商驱动层,根据设备驱动发来的请求,完成对硬件的操作,包括寄存器的设置和地址映射
---------------------------------------------------------------------------------------------------------------------------------
硬件
gpio如何实现点灯:
1,修改设备树,添加灯的驱动
查看Linux内核帮助文档:内核目录/Documentation/devicetree/bindings/gpio
编写自己的设备树
2,源码目录下,make dtbs 编译设备树,并拷贝到tftpboot目录下,开发板上电,待内核加载
3,编写驱动控制
4,编译驱动文件,通过串口工具安装
gpio函数:
1.获取gpio编号of_get_named_gpio(node,"myled",0)node节点,键,索引号
2.申请gpio编号gpio_request
3.设置gpio输出模式gpio_direction_output
4.设置对应的值gpio_set_value
5.在出口中释放gpio编号,否则下次无法获取gpio_free
新版gpio获取函数:
gpio编号用结构体指针存放
gpiod_get_from_of_node
gpiod_direction_output
gpiod_direction_input
gpiod_put 释放gpio编号
获取设备树节点的三种方式:
1.struct device_node *of_find_node_by_path(const char *path)通过路径获取设备树节点信息
2.of_find_node_by_name
3.of_find_compatible_node
驱动代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
//定义结构体获取设备树节点信息
struct device_node *node;
int gpiono;//存放老版本
struct gpio_desc *gpinum;//存放新版本
int ret;
static int __init mycdev_init(void)
{
//1.通过名字获取设备节点信息
node=of_find_node_by_name(NULL,"myleds");
if(node==NULL)
{
printk("failed\n");
return -EFAULT;
}
printk("succeed\n");
//获取gpio编号
gpiono=of_get_named_gpio(node,"myled2",0);
if(gpiono<0)
{
printk("获取gpio编号失败\n");
return gpiono;
}
printk("get gpiono succeed\n");
//申请gpio使用权
ret=gpio_request(gpiono,NULL);
if(ret)
{
printk("申请gpio编号失败\n");
return ret;
}
printk("gpio_request succeed\n");
//设置gpio管脚输出模式
gpio_direction_output(gpiono,0);
//点亮led2
gpio_set_value(gpiono,1);
//方法2新的gpio子系统
//获取并申请gpio编号
gpinum=gpiod_get_from_of_node(node,"myled3",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpinum))
{
printk("获取gpio编号失败\n");
//将错误码指针转换成错误码
return PTR_ERR(gpinum);
}
printk("获取gpio编号成功\n");
//设置管脚输出模式
gpiod_direction_output(gpinum,0);
//点亮led3
gpiod_set_value(gpinum,1);
return 0;
}
static void __exit mycdev_exit(void)
{
//熄灭灯
gpio_set_value(gpiono,0);
//卸载驱动
gpio_free(gpiono);
//熄灭led3
gpiod_set_value(gpinum,0);
//卸载驱动
gpiod_put(gpinum);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");