【驱动开发】基于GPIO子系统编写LED驱动,编写应用程序进行测试设置定时器,5秒钟打印一次hello world
基于GPIO子系统编写LED驱动,编写应用程序进行测试,设置定时器,5秒钟打印一次hello world
驱动程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
/*
myled
{
led1-gpio=<&gpioe 10 0>;
led2-gpio=<&gpiof 10 0>;
led3-gpio=<&gpioe 8 0>;
};
*/
// 分配定时器对象
struct timer_list mytimer;
struct device_node *dnode;
int gpiono1, gpiono2, gpiono3;
// 定时器处理函数
int n = 1;
int count = 0;
int trigger_count = 5;
void mytimer_function(struct timer_list *timer)
{
count++;
if (count == trigger_count)
{
printk("Hello World\n");
count = 0;
}
mod_timer(timer, jiffies + 5 * HZ);
switch (n)
{
case 1:
gpio_set_value(gpiono1, !gpio_get_value(gpiono1));
n++;
break;
case 2:
gpio_set_value(gpiono2, !gpio_get_value(gpiono2));
n++;
break;
case 3:
gpio_set_value(gpiono3, !gpio_get_value(gpiono3));
n = 1;
break;
default:
break;
}
mod_timer(timer, jiffies + HZ);
}
int gpio_led1(int gpiono, struct device_node *dnode)
{
// 根据设备树节点解析gpio编号
gpiono = of_get_named_gpio(dnode, "led1-gpio", 0);
if (gpiono < 0)
{
printk("解析led1_gpio编号失败\n");
return -EIO;
}
printk("解析led1_gpio编号成功\n");
// 申请gpio编号
gpio_request(gpiono, NULL);
// 设置gpio为输出并且初始化数值为0
gpio_direction_output(gpiono, 0);
return gpiono;
}
int gpio_led2(int gpiono, struct device_node *dnode)
{
// 根据设备树节点解析gpio编号
gpiono = of_get_named_gpio(dnode, "led2-gpio", 0);
if (gpiono < 0)
{
printk("解析led2_gpio编号失败\n");
return -EIO;
}
printk("解析led2_gpio编号成功\n");
// 申请gpio编号
gpio_request(gpiono, NULL);
// 设置gpio为输出并且初始化数值为0
gpio_direction_output(gpiono, 0);
return gpiono;
}
int gpio_led3(int gpiono, struct device_node *dnode)
{
// 根据设备树节点解析gpio编号
gpiono = of_get_named_gpio(dnode, "led3-gpio", 0);
if (gpiono < 0)
{
printk("解析led3_gpio编号失败\n");
return -EIO;
}
printk("解析led3_gpio编号成功\n");
// 申请gpio编号
gpio_request(gpiono, NULL);
// 设置gpio为输出并且初始化数值为0
gpio_direction_output(gpiono, 0);
return gpiono;
}
static int __init mycdev_init(void)
{
// 解析设备树节点信息
dnode = of_find_node_by_path("/myled");
if (dnode == NULL)
{
printk("解析设备树节点失败\n");
return -ENXIO;
}
gpiono1 = gpio_led1(gpiono1, dnode);
gpiono2 = gpio_led2(gpiono2, dnode);
gpiono3 = gpio_led3(gpiono3, dnode);
// 初始化定时器对象
timer_setup(&mytimer, mytimer_function, 0);
mytimer.expires = jiffies + HZ; // 定时1s
// 注册定时器
add_timer(&mytimer);
return 0;
}
static void __exit mycdev_exit(void)
{
//注销定时器
del_timer(&mytimer);
gpiod_set_value(gpiono1,0);
//释放GPIO编号
gpiod_put(gpiono1);
//注销定时器
del_timer(&mytimer);
gpiod_set_value(gpiono2,0);
//释放GPIO编号
gpiod_put(gpiono2);
//注销定时器
del_timer(&mytimer);
gpiod_set_value(gpiono3,0);
//释放GPIO编号
gpiod_put(gpiono3);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");