GPIO子系统框架图:
LED等的硬件连接图:
新增设备树结点:
在linux内核源码目录/arch/arm/boot/dts目录下,打开对应dts文件,添加如下设备结点
注:根据linux内核源码目录/Documentation/devicetree/bindings/gpio/下的gpio.txt文件中的例子编写对应新增的设备树结点
驱动代码:
#include <linux/init.h>
#include <linux/module.h>
#include<linux/timer.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
//分配定时器对象
struct timer_list timer;
struct device_node *dnode;
int gpion1,gpion2,gpion3; //用于记录申请到的gpio编号
//定时器处理函数
void timer_handler(struct timer_list *timer)
{
gpio_set_value(gpion1,!gpio_get_value(gpion1));
gpio_set_value(gpion2,!gpio_get_value(gpion2));
gpio_set_value(gpion3,!gpio_get_value(gpion3));
mod_timer(timer,jiffies+HZ);
}
static int __init mycdev_init(void)
{
//解析设备树节点
dnode = of_find_node_by_name(NULL,"myleds");
if(dnode == NULL)
{
printk("解析设备树节点失败\n");
return -ENXIO;
}
printk("解析设备树节点成功\n");
//根据设备树节点解析gpio编号
gpion1 = of_get_named_gpio(dnode,"led1",0); //LED1:gpioe 10
if(gpion1 < 0)
{
printk("解析gpio编号失败\n");
return -ENXIO;
}
gpion2 = of_get_named_gpio(dnode,"led2",0); //LED2:gpiof 10
if(gpion2 < 0)
{
printk("解析gpio编号失败\n");
return -ENXIO;
}
gpion3 = of_get_named_gpio(dnode,"led3",0); //LED3:gpioe 8
if(gpion3 < 0)
{
printk("解析gpio编号失败\n");
return -ENXIO;
}
printk("解析gpio编号成功\n");
//申请gpio编号
gpio_request(gpion1,NULL);
gpio_request(gpion2,NULL);
gpio_request(gpion3,NULL);
//设置gpio为输出并且初始化数值为0
gpio_direction_output(gpion1,0);
gpio_direction_output(gpion2,0);
gpio_direction_output(gpion3,0);
//定时器初始化
//指定定时阈值
timer.expires = jiffies+HZ;
timer_setup(&timer,timer_handler,0);
add_timer(&timer);
return 0;
}
static void __exit mycdev_exit(void)
{
//注销gpio编号
gpio_free(gpion1);
gpio_free(gpion2);
gpio_free(gpion3);
printk("注销gpio编号成功\n");
//注销定时器
del_timer(&timer);
printk("注销定时器成功\n");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");