[linux驱动开发--API框架]--platform、gpio、pinctrl

1. 结构体定义和实例化

// 这个结构体样式并不固定,按需增减成员,可以参考内核的其他驱动代码
struct leddev_dev{dev_t devid;                /* 设备号*/struct cdev cdev;           /* cdev*/struct class *class;        /* 类*/struct device *device;      /* 设备*/int major;                  /* 主设备号*/	struct device_node *node;   /* LED设备节点*/int led0;                   /* LED灯GPIO标号*/
}leddev;/*这个结构体最少也要有这些成员,可以参考内核的驱动代码*/
struct platform_driver led_platform_driver = {.probe = led_probe,.driver = {.name = "leds-platform_gpio",.owner = THIS_MODULE,.of_match_table = led_ids,}
};

2. 注册与卸载配套API

注意:顺序注册,逆序卸载

  1. 执行led_platform_driver_initled_platform_driver_exit函数
module_init(led_platform_driver_init);
module_exit(led_platform_driver_exit);
  1. 注册卸载平台驱动
DriverState = platform_driver_register(&led_platform_driver);
platform_driver_unregister(&led_platform_driver);
  1. /proc/devices/LEDDEV_NAME下生成名称对应LEDDEV_NAME的主设备号
alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME);
unregister_chrdev_region(leddev.devid, LEDDEV_CNT);
cdev_init(&leddev.cdev, &led_fops);
cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);
cdev_del(&leddev.cdev);	
  1. /sys/class/LEDDEV_NAME下创建类
leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);
class_destroy(leddev.class);
  1. /dev/LEDDEV_NAME下创建设备节点,在/sys/devices/virtual/gpio_lab_led下创建设备
leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME);
device_destroy(leddev.class, leddev.devid);
  1. 试验了一下,现在的内核不需要显式释放leddev.led0
leddev.led0 = of_get_named_gpio(leddev.node, "led-gpio", 0);
gpio_direction_output(leddev.led0, 1);

3. 完整代码(仅供参考)

#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/of_gpio.h>
#define LEDDEV_CNT      1
#define LEDDEV_NAME     "gpio_lab_led"
/* leddev设备结构体 */
struct leddev_dev{dev_t devid;				/* 设备号	*/struct cdev cdev;			/* cdev		*/struct class *class;		/* 类 		*/struct device *device;		/* 设备		*/int major;					/* 主设备号	*/	struct device_node *node;	/* LED设备节点 */int led0;					/* LED灯GPIO标号 */
};struct leddev_dev leddev; 		/* led设备 */static int led_open(struct inode *inode, struct file *filp)
{return 0;
}static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}// /* 设备操作函数 */
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.write = led_write,
};/*----------------平台驱动函数集-----------------*/
static int led_probe(struct platform_device *pdv)
{printk(KERN_EMERG "led driver and device was matched!\r\n");// 注册的设备ID保存到leddev.devid// LEDDEV_NAME对应/proc/devices下的名字alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME);leddev.major = MAJOR(leddev.devid);printk(KERN_EMERG "\tleddev.major = %d\n",leddev.major);// 绑定操作函数cdev_init(&leddev.cdev, &led_fops);// 绑定设备IDcdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);/* 3、创建类      */leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);if (IS_ERR(leddev.class)) {return PTR_ERR(leddev.class);}/* 4、创建设备 */leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME);if (IS_ERR(leddev.device)) {return PTR_ERR(leddev.device);}leddev.node = of_find_node_by_path("/lab_led");if(leddev.node == NULL){printk(KERN_EMERG "get lab_led failed!  \n");}leddev.led0 = of_get_named_gpio(leddev.node, "gpios", 0);printk("led = %d \n",leddev.led0);/*设置gpio输出高电平*/gpio_direction_output(leddev.led0, 1);return 0;
}static const struct of_device_id led_ids[] = {{ .compatible = "gpio_lab_led"},{ /* sentinel */ }
};/*定义平台设备结构体*/
struct platform_driver led_platform_driver = {.probe = led_probe,.driver = {.name = "leds-platform_gpio",.owner = THIS_MODULE,.of_match_table = led_ids,}
};/*
*驱动初始化函数
*/
static int __init led_platform_driver_init(void)
{int DriverState;DriverState = platform_driver_register(&led_platform_driver);printk(KERN_EMERG "\tDriverState is %d\n",DriverState);return 0;
}/*
*驱动注销函数
*/
static void __exit led_platform_driver_exit(void)
{printk(KERN_EMERG "led_test exit!\n");gpio_direction_output(leddev.led0, 0);device_destroy(leddev.class, leddev.devid);class_destroy(leddev.class);cdev_del(&leddev.cdev);				/*  删除cdev */unregister_chrdev_region(leddev.devid, LEDDEV_CNT); /* 注销设备号 */platform_driver_unregister(&led_platform_driver);
}
module_init(led_platform_driver_init);
module_exit(led_platform_driver_exit);MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从书本到代码:人工智能如何改变教育游戏规则?

内容概要 随着时代的发展&#xff0c;人工智能在教育领域展现出前所未有的潜力&#xff0c;成为推动教育改革的重要力量。它不仅仅是一种技术工具&#xff0c;更是一种变革的催化剂&#xff0c;促使传统教育模式必须进行自我反思和更新。通过利用智能算法&#xff0c;教育者可…

发布一个npm组件库包

Webpack 配置 (webpack.config.js) const path require(path); const MiniCssExtractPlugin require(mini-css-extract-plugin); const CssMinimizerPlugin require(css-minimizer-webpack-plugin); const TerserPlugin require(terser-webpack-plugin);module.exports {…

C#语言:现代软件开发的核心工具

在当今快速发展的软件行业&#xff0c;C#&#xff08;发音为“C sharp”&#xff09;已成为开发人员广泛采用的一种编程语言。它由微软公司开发&#xff0c;旨在提供强大的功能、简洁的语法和广泛的适用性。自2000年首次发布以来&#xff0c;C#已成为构建各种类型应用程序的理想…

若Git子模块的远端地址发生了变化本地应该怎么调整

文章目录 前言git submodule 相关命令解决方案怎么保存子模块的版本呢总结 前言 这个问题复杂在既有Git又有子模块&#xff0c;本身Git的门槛就稍微高一点&#xff0c;再加上子模块的运用&#xff0c;一旦出现这种远端地址发生修改的情况会让人有些懵&#xff0c;不知道怎么处…

长视频为什么在广告市场上节节败退?

作者&#xff1a;刀客doc 在广告市场&#xff0c;长视频网站的吸引力在减小&#xff0c;这是不争的事实。不过最近我发现&#xff0c;这一趋势还在加剧。 近期&#xff0c;一份QuestMobile的数据预测了互联网各类媒介的市场份额。其中5年来&#xff0c;在线视频广告的份额年年…

Kubernetes-编排工具篇-01-Kustomize与Helm对比

Kustomize与Helm对比 0、前言 K8s 是一个开源容器编排平台&#xff0c;可自动执行容器化应用程序的部署、扩展和管理。近年来&#xff0c;K8s 已成为采用云原生架构和容器化技术的组织的标准。 但是由于K8s的复杂性&#xff0c;所以很多公司以及开源组织都在开发相关的工具来…

量子电路的实现 基于ibm的qiskit

量子计算的物理实现 量子计算的实现有几种方式&#xff0c;最常用的就是超导量子计算机&#xff0c;它的量子处理器是用超导传输量子比特构建的&#xff0c;它是由一个约瑟夫森结和一个并联的电容器组成的电路。约瑟夫森结是一种非线性电感&#xff0c;由两层重叠的超导…

【AIGC】如何通过ChatGPT轻松制作个性化GPTs应用

创建个性化的GPTs应用是一个涉及技术、设计和用户体验的过程。以下是详细步骤&#xff1a; ###1.确定应用目标和用户群体 在开始之前&#xff0c;你需要明确你的应用的目标和目标用户。这将帮助你在设计、开发和个性化方面做出相应的决策。例如&#xff0c;如果你的应用是为了…

cmake中execute_process详解

execute_process 是 CMake 中一个非常强大的命令&#xff0c;用于在构建过程中执行外部程序或脚本。它提供了丰富的选项来控制执行过程&#xff0c;并可以捕获输出、错误和返回码。以下是 execute_process 的详细解析&#xff1a; 基本语法 execute_process(COMMAND <comm…

141/142题环形链表

本题返回环入口的位置。使用快慢指针&#xff0c;快指针每次移动两个&#xff0c;慢指针每次移动一个。设前一段距离是a,进入环内到slow和fast相遇的地点距离是b&#xff0c;环内剩下的距离是c&#xff0c;如图所示。 环的长度是bc 慢指针移动距离是ab 快指针移动距离是abk(bc…

Linux-2

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;linux基础之病毒编写&#xff08;完结&#xff09;_哔哩哔哩_bilibili 一、Linux目录介绍 /bin&#xff1a;二进制可执行命令 /etc&#xff1a;…

快速入门Zookeeper

Zookeeper ZooKeeper作为一个强大的开源分布式协调服务&#xff0c;扮演着分布式系统中至关重要的角色。它提供了一个中心化的服务&#xff0c;用于维护配置信息、命名、提供分布式同步以及提供组服务等。通过其高性能和可靠的特性&#xff0c;ZooKeeper能够确保在复杂的分布式…

SpringBoot环境下的共享汽车管理策略

3系统分析 3.1可行性分析 通过对本共享汽车管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本共享汽车管理系统采用SSM框架&#xff0c;JAVA作为开发语…

确定图像的熵和各向异性 Halcon entropy_gray 解析

1、图像的熵 1.1 介绍 图像熵&#xff08;image entropy&#xff09;是图像“繁忙”程度的估计值&#xff0c;它表示为图像灰度级集合的比特平均数&#xff0c;单位比特/像素&#xff0c;也描述了图像信源的平均信息量。熵指的是体系的混乱程度&#xff0c;对于图像而言&#…

什么是多因素身份验证(MFA)的安全性?

多因素身份验证(MFA)简介 什么是MFA 多因素身份验证(MFA)是一种安全过程&#xff0c;要求用户在授予对系统、应用程序或账户的访问权限之前提供两种或多种形式的验证。仅使用单个因素&#xff08;通常是用户名和密码&#xff09;保护资源会使它们容易受到泄露&#xff0c;添加…

特色3D打印机stm32迷你8轴双核心主板

我自己设计的3D打印机主板 1. 这是一块迷你的8轴主板, 主板尺寸为100mm*75mm, 使用一个8cm静音风扇散热足够了2. 这是一个带有保护的板子, 驱动上的gpio具有过压保护功能, 能够直接抗住24V的冲击, 意味着一个驱动炸了, 板子不烧, 并且其他的驱动也没事, 主板支持自动关机3. 8…

【LeetCode:3242. 设计相邻元素求和服务 + 模拟 + 哈希表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

GIF图片格式详解(二)

gif历史请参考上一篇《GIF图片格式详解&#xff08;一&#xff09;》&#xff0c;或直接访问博客地址&#xff1a;https://blog.whatsroot.xyz/2023/12/16/all-about-gif/ 文件格式概述 GIF格式采用调色板模式&#xff0c;即有一个颜色表&#xff0c;每种颜色可以使用RGB24格…

TypeScript 基础语法及使用

文章目录 1、概述2、快速使用3、常用类型4、基础类型5、联合类型6、函数类型7、对象类型 & 接口interface 1、概述 TypeScript&#xff08;简称 TS&#xff09;是JavaScript的超集&#xff08;继承了JS全部语法&#xff09;是微软开发的开源编程语言&#xff0c;可以在任何…

linux---vi和vim快捷键

linux---vi和vim快捷键 1、vi2、vim 1、vi 普通模式&#xff08;Normal Mode&#xff09;&#xff1a;i 进入插入模式&#xff08;Insert Mode&#xff09; x 删除光标所在位置的字符 dd 删除整行 yy 复制整行 p 粘贴 u 撤销 Ctrl r 重做 Shift G 快速移动光标到文件的最后…