编写led灯的设备树结点并驱动led灯点亮

目录

一、GPIO子系统

        1.1GPIO子系统框架图

二、gpio设备树的编写

        2.1 led灯的硬件连接图

三、添加led设备树结点

四、编写驱动代码

五、 Makefile

六、实现结果


一、GPIO子系统

        1.1GPIO子系统框架图

二、gpio设备树的编写

        2.1 led灯的硬件连接图

1.解析对应设备的设备树节点
    struct device_node *of_find_node_by_name(struct device_node *from,
                                            const char *name);
2.根据解析得到的设备树节点结构体去解析得到对应的gpio编号
    int of_get_named_gpio(struct device_node *np,
                           const char *propname, int index)
3.向内核申请要使用的gpio编号
    int gpio_request(unsigned gpio, const char *label)
4.设置gpio编号对应的gpio管脚为输出模式,并且输出电平(0:低电平,1:高电平)
    int gpio_direction_output(unsigned gpio, int value)
5.设置输出指定的数值(0:低电平,1:高电平)
    void gpio_set_value(unsigned gpio, int value)
6.将注册的gpio编号在内核中注销
    void gpio_free(unsigned gpio);

三、添加led设备树结点

在/home/ubuntu/linux-5.10.61/arch/arm/boot/dts下

打开stm32mp157a-fsmp1a.dts文件

添加如下设备结点

四、编写驱动代码

驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/of.h>
#include <linux/timer.h>
#include<linux/of_gpio.h>
/*myleds{
    led1=<&gpioe 10 0>;
    led2=<&gpiof 10 0>;
    led3=<&gpioe 8 0>;
};*/
struct device_node *dnode;
int gpiono1,gpiono2,gpiono3;
//定义一个定时器变量
struct timer_list timer;
//定时器处理函数
void timer_handler(struct timer_list *timer)
{
    gpio_set_value(gpiono1,!gpio_get_value(gpiono1));
    gpio_set_value(gpiono2,!gpio_get_value(gpiono2));
    gpio_set_value(gpiono3,!gpio_get_value(gpiono3));
    printk("LED1 light\n");
    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 -ENOENT;
    }
    printk("设备树节点信息解析成功\n");

    //根据设备树节点解析gpio编号
    gpiono1 = of_get_named_gpio(dnode,"led1",0);
    if(gpiono1<0)
    {
        printk("解析gpio编号失败\n");
        return -EIO;
    }
    gpiono2 = of_get_named_gpio(dnode,"led2",0);
    if(gpiono1<0)
    {
        printk("解析gpio编号失败\n");
        return -EIO;
    }
    gpiono3 = of_get_named_gpio(dnode,"led3",0);
    if(gpiono1<0)
    {
        printk("解析gpio编号失败\n");
        return -EIO;
    }
    printk("解析gpio编号成功\n");

    //申请gpio编号
    gpio_request(gpiono1,NULL);
    gpio_request(gpiono2,NULL);
    gpio_request(gpiono3,NULL);
    //设置gpio为输出并且初始化述职为0
    gpio_direction_output(gpiono1,0);
    gpio_direction_output(gpiono2,0);
    gpio_direction_output(gpiono3,0);
    //定时器初始化
    //指定定时阈值
    timer.expires=jiffies+HZ;
    timer_setup(&timer,timer_handler,0);
    add_timer(&timer);
    return 0;

}
static void __exit mycdev_exit(void)
{
    gpio_free(gpiono1);
    gpio_free(gpiono2);
    gpio_free(gpiono3);
    del_timer(&timer);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

五、 Makefile

#定义一个变量,存放架构
ARCH ?= x86
#定义一个变量,存放文件名
modname ?= demo

ifeq ($(ARCH),arm)
#定义一个变量,存放linux内核源码目录
KERNEDIR:=/home/ubuntu/linux-5.10.61
else
#定义一个变量,存放ubuntu的linux内核源码目录,生成X86架构
KERNEDIR:=/lib/modules/$(shell uname -r)/build
endif
#定义一个变量,开启一个终端,执行pwd命令
PWD:=$(shell pwd)

all:
	@#-C:跳转到内核顶层目录下,读取内核顶层目录下的Makefile文件
	@#在内核源码顶层目录下执行:make M=$(shell pwd) modules
	@#M=$(shell pwd):回到当前目录下,只编译当前目录下的文件
	@#make modules:采用模块化方式进行编译
	make -C $(KERNEDIR) M=$(shell pwd) modules

clean:
	make -C $(KERNEDIR) M=$(shell pwd) clean
#指定模块化方式编译的文件
obj-m:=$(modname).o

六、实现结果

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值