利用gpiod子系统实现开发板六盏灯,安装驱动点亮,卸载驱动熄灭
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
/*
myleds{
core-leds{
leds = <&gpioz 5 0>,<&gpioz 6 0>,<&gpioz 7 0>;
};
extend-leds{
led1 = <&gpioe 10 0>;
led2 = <&gpiof 10 0>;
led3 = <&gpioe 8 0>;
};
};
*/
struct device_node *node;
struct device_node *core_node;
struct device_node *extend_node;
struct gpio_desc *core_desc[3];
struct gpio_desc *extend_desc[3];
char *extend_leds[3] = {"led1", "led2", "led3"};
// 入口
static int __init demo_init(void)
{
int i;
// 获取父结点
node = of_find_node_by_path("/myleds");
if (node == NULL)
{
printk("of_find_node_by_path is error\n");
return -EIO;
}
// 获取core子节点
core_node = of_get_child_by_name(node, "core-leds");
if (core_node == NULL)
{
printk("core of_get_child_by_name is error\n");
return -EIO;
}
// 获取extend子节点
extend_node = of_get_child_by_name(node, "extend-leds");
if (node == NULL)
{
printk("extend of_get_child_by_name is error\n");
return -EIO;
}
for (i = 0; i < 3; i++)
{
// 获取gpio结构体
core_desc[i] = gpiod_get_from_of_node(core_node, "leds", i, GPIOD_OUT_HIGH, NULL);
// 申请gpio编号
gpiod_get_value(core_desc[i]);
// 设置gpio输出为1
gpiod_direction_output(core_desc[i], 1);
}
for (i = 0; i < 3; i++)
{
// 获取gpio结构体
extend_desc[i] = gpiod_get_from_of_node(extend_node, extend_leds[i], 0, GPIOD_OUT_HIGH, NULL);
// 申请gpio编号
gpiod_get_value(extend_desc[i]);
// 设置gpio输出为1
gpiod_direction_output(extend_desc[i], 1);
}
return 0;
}
// 出口
static void __exit demo_exit(void)
{
int i;
for (i = 0; i < 3; i++)
{
// 设置gpio输出为0
gpiod_direction_output(core_desc[i], 0);
// 释放gpio编号
gpiod_put(core_desc[i]);
}
for (i = 0; i < 3; i++)
{
// 设置gpio输出为0
gpiod_direction_output(extend_desc[i], 0);
// 释放gpio编号
gpiod_put(extend_desc[i]);
}
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL"); // 许可证
使用linux中断子系统完成三个按键编写
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
/*
mykeys{
interrupt-parent=<&gpiof>;
interrupts = <9 0>,<7 0>,<8 0>;
};
*/
irqreturn_t key1_irq_handler(int irq, void *dev)
{
int key = (int)dev;
switch (key)
{
case 0:
printk("key1 down!!!\n");
break;
case 1:
printk("key2 down!!!\n");
break;
case 2:
printk("key3 down!!!\n");
break;
default:
break;
}
return IRQ_HANDLED;
}
unsigned int irqnu[3];
char *irname[3] = {"key1", "key2", "key3"};
struct device_node *node;
// 入口
static int __init demo_init(void)
{
int i;
int ret;
// 获取结点
node = of_find_node_by_path("/mykeys");
if (node == NULL)
{
printk("of_find_node_by_path is error\n");
return -EIO;
}
for (i = 0; i < 3; i++)
{
// 获取软中断号
irqnu[i] = irq_of_parse_and_map(node, i);
// 注册中断子系统
ret = request_irq(irqnu[i], key1_irq_handler, IRQF_TRIGGER_FALLING, irname[i], (void *)i);
if (ret < 0)
{
printk("%d request_irq is error\n", irqnu[i]);
return -EIO;
}
}
return 0;
}
// 出口
static void __exit demo_exit(void)
{
int i;
for (i = 0; i < 3; i++)
{
// 注销中断
free_irq(irqnu[i], NULL);
}
}
module_exit(demo_exit);
module_init(demo_init);
MODULE_LICENSE("GPL"); // 许可证