当前位置: 首页 > article >正文

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

文章目录

前言

一、设备树配置

1.1 添加 pinctrl 节点

1.2 添加 LED 设备节点

二、编写驱动程序

2.1 驱动程序框架

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 功能。


http://www.kler.cn/a/554919.html

相关文章:

  • 数据库基础1
  • 在亚马逊云科技大模型平台Bedrock上部署DeepSeek-R1蒸馏模型
  • 设计模式 之 建造者模式(C++)
  • C# 索引器 使用详解
  • DeepSeek 新注意力架构NSA
  • 【杂记】机器学习
  • buf存储器缓存
  • el-message自定义HTML包含按钮点击事件
  • Android Studio安装配置及运行
  • Jetpack Architecture系列教程之(三)——ViewModel控制器
  • 【tips】el-select没有赋值但是初始化回显了
  • 从零开始构建一个小型字符级语言模型的完整详细教程(基于Transformer架构)
  • vue3-05reactive定义对象类型的响应式数据(不能进行基本类型数据的响应式)
  • 使用 Flask 和 pdfkit 生成带透明 PNG 盖章的 PDF 并上传到阿里云 OSS
  • 【Linux网络】认识协议、Mac/IP地址和端口号、网络字节序、socket套接字
  • Day15-后端Web实战-登录认证——会话技术JWT令牌过滤器拦截器
  • AUTOSAR从入门到精通-【自动驾驶】BEV感知(二)
  • 独立开发者灵感日报:关系代理,而不是另一个 CRM
  • Unity面板介绍_菜单栏(23.1.1)
  • 【C++委托与事件】函数指针,回调机制,事件式编程与松耦合的设计模式(下)