嵌入式 Linux:使用设备树驱动GPIO全流程

文章目录

前言

一、设备树配置

[1.1 添加 pinctrl 节点](#1.1 添加 pinctrl 节点)

[1.2 添加 LED 设备节点](#1.2 添加 LED 设备节点)

二、编写驱动程序

[2.1 驱动程序框架](#2.1 驱动程序框架)

[2.2 编译驱动程序](#2.2 编译驱动程序)

三、测试

总结


前言

在嵌入式 Linux 开发中,设备树(Device Tree)和 GPIO 子系统是控制硬件设备的重要工具。本文将详细介绍如何使用设备树和 GPIO 子系统驱动 LED 灯,包括在设备树中添加 pinctrl 节点、设备节点,以及编写驱动程序的全流程。


**一、**设备树配置

1.1 添加 pinctrl 节点

pinctrl 节点用于配置 GPIO 引脚的功能和电气属性。在实际开发中,通常在设备树文件中,即dts文件中添加对应的pinctrl节点来对对应GPIO引脚的属性进行定义。如下即为对GPIO1_03引脚配置为GPIO模式等。

1.2 添加 LED 设备节点

在设备树中添加 LED 设备节点,以描述 LED 的 GPIO 引脚和属性,如下即为在设备树根节点下添加一个gpioled设备节点,其中引用了定义的pinctrl节点中定义的属性。

二、编写驱动程序

2.1 驱动程序框架

在驱动文件中,主要完成对gpioled_dev结构体的定义,四大文件操作函数的定义,初始化函数和退出函数的定义,起终点在于初始化函数的定义,如下几位初始化函数的定义:

复制代码
static int __init led_init(void)
{
	int ret = 0;

	/* 设置LED所使用的GPIO */
	/* 1、获取设备节点:gpioled */
	gpioled.nd = of_find_node_by_path("/gpioled");//在设备树中查找gpioled节点
	if(gpioled.nd == NULL) {
		printk("gpioled node not find!\r\n");
		return -EINVAL;
	} else {
		printk("gpioled node find!\r\n");
	}

	/* 2、 获取设备树中的gpio属性,得到LED所使用的LED编号 */
	gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0);
	if(gpioled.led_gpio < 0) {
		printk("can't get led-gpio");
		return -EINVAL;
	}
	printk("led-gpio num = %d\r\n", gpioled.led_gpio);

	/* 3、设置GPIO1_IO03为输出,并且输出高电平,默认关闭LED灯 */
	ret = gpio_direction_output(gpioled.led_gpio, 1);
	if(ret < 0) {
		printk("can't set gpio!\r\n");
	}

	/* 注册字符设备驱动 */
	/* 1、创建设备号 */
	if (gpioled.major) {		/*  定义了设备号 */
		gpioled.devid = MKDEV(gpioled.major, 0);
		register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME);
	} else {						/* 没有定义设备号 */
		alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);	/* 申请设备号 */
		gpioled.major = MAJOR(gpioled.devid);	/* 获取分配号的主设备号 */
		gpioled.minor = MINOR(gpioled.devid);	/* 获取分配号的次设备号 */
	}
	printk("gpioled major=%d,minor=%d\r\n",gpioled.major, gpioled.minor);	
	
	/* 2、初始化cdev */
	gpioled.cdev.owner = THIS_MODULE;//与定义的gpioled_fops关联在一起
	cdev_init(&gpioled.cdev, &gpioled_fops);
	
	/* 3、添加一个cdev */
	cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);//添加到内核

	/* 4、创建类 */
	gpioled.class = class_create(THIS_MODULE, GPIOLED_NAME);
	if (IS_ERR(gpioled.class)) {
		return PTR_ERR(gpioled.class);
	}//创建类和设备节点,使用户得以和内核交互

	/* 5、创建设备 */
	gpioled.device = device_create(gpioled.class, NULL, gpioled.devid, NULL, GPIOLED_NAME);
	if (IS_ERR(gpioled.device)) {
		return PTR_ERR(gpioled.device);
	}
	return 0;
}

即设置并注册一个控制LED的字符设备驱动初始化函数,首先查找设备树节点,随后在设备树节点中获取LED的GPIO编号,配置对应的GPIO。以及注册字符设备驱动,创建类和设备节点。总体来说,即实现了从解析设备树、配置GPIO、注册字符设备驱动,到最后创建可被用户空间程序访问的设备节点。这些步骤确保了驱动程序能够正确地初始化硬件,并提供了一个与之交互的接口,让用户空间的应用程序可以控制LED的状态。

2.2 编译驱动程序

使用make命令交叉编译编写的驱动文件,

随后将编译出的内核模块文件加载内核中,即.ko文件:

三、测试

在嵌入式linux设备端,查看设备树中添加的gpioled节点:

加载驱动,使用modprobe命令将加载gpioled.ko

最后,使用测试文件对驱动进行测试,观察开发板状态,成功实现通过pinctrl和gpio子系统来完成对嵌入式linux系统中的GPIO进行控制。


总结

通过设备树和 GPIO 子系统驱动 LED 灯的流程如下:

  1. 在设备树中添加 pinctrl 节点,配置 GPIO 引脚。

  2. 在设备树中添加 LED 设备节点,描述 LED 的 GPIO 引脚和属性。

  3. 编写驱动程序,使用 GPIO 子系统控制 LED 灯。

  4. 编译并加载驱动,测试 LED 功能。

相关推荐
HZero.chen20 小时前
Linux字符串处理
linux·string
张童瑶20 小时前
Linux SSH隧道代理转发及多层转发
linux·运维·ssh
汪汪队立大功12320 小时前
什么是SELinux
linux
石小千20 小时前
Linux安装OpenProject
linux·运维
柏木乃一20 小时前
进程(2)进程概念与基本操作
linux·服务器·开发语言·性能优化·shell·进程
Lime-309021 小时前
制作Ubuntu 24.04-GPU服务器测试系统盘
linux·运维·ubuntu
CloudJourney21 小时前
从Unix到OpenEuler及其关键协议解析
服务器·unix
百年渔翁_肯肯21 小时前
Linux 与 Unix 的核心区别(清晰对比版)
linux·运维·unix
胡闹5421 小时前
Linux查询防火墙放过的端口并额外增加需要通过的端口命令
linux·运维·windows
AI科技星1 天前
质量定义方程常数k = 4π m_p的来源、推导与意义
服务器·数据结构·人工智能·科技·算法·机器学习·生活