基于GPIO子系统的LED驱动程序

这两个系统属于软件层,让我们不用直接对硬件配置,一般由芯片出产商写好,我们只要基于它们改就行。

设备树操作

1.使用官方的工具来编写pinctrl设置gpio的设备树代码。
如图,生成代码
![在这里插入图片描述](https://img-blog.csdnimg.cn/b3a6ab2177014f73a43c1ea1e5f0aa14.png在这里插入图片描述
2.将生成的代码复制带设备树文件中,并修改子节点名字位myled_gpio_for_sys

,
3.添加一个设备节点

pinctrl-names:“default”,表示只有一个状态
pinctrl-0 = "&myled_gpio_for_sys"表示当设备处于第一个状态时,引脚按照myled_gpio_for_sys子节点的属性来复用。
led-gpios = <&gpio5 3 GPIO_ACTIVE_LOW> 用来描述LED引脚
参数:
&gpio5 表示CD引脚所使用的IO属于GPIO5组
3 表示GPIO5组的第3号IO
GPIO_ACTIVE_LOW 表示低电平有效

在这里插入图片描述

最后就可以在驱动代码中获得、设置、读写GPIO引脚,
记得包含头文件

#include <linux/gpio/consumer.h> // descriptor-based

在这里插入图片描述

驱动代码

#include <linux/module.h>
#include <linux/platform_device.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>/* 1. 确定主设备号                                                                 */
static int major = 0;
static struct class *led_class;
static struct gpio_desc *led_gpio;/* 3. 实现对应的open/read/write等函数,填入file_operations结构�?                  */
static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/* write(fd, &val, 1); */
static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{int err;char status;//struct inode *inode = file_inode(file);//int minor = iminor(inode);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = copy_from_user(&status, buf, 1);/* 根据次设备号和status控制LED */gpiod_set_value(led_gpio, status);return 1;
}static int led_drv_open (struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* 根据次设备号初始化LED */gpiod_direction_output(led_gpio, 0);return 0;
}static int led_drv_close (struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/* 定义自己的file_operations结构�?                                             */
static struct file_operations led_drv = {.owner	 = THIS_MODULE,.open    = led_drv_open,.read    = led_drv_read,.write   = led_drv_write,.release = led_drv_close,
};/* 4. 从platform_device获得GPIO*    把file_operations结构体告诉内核:注册驱动程序*/
static int chip_demo_gpio_probe(struct platform_device *pdev)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* 4.1 设备树中定义�? led-gpios=<...>;	*/led_gpio = gpiod_get(&pdev->dev, "led", 0);if (IS_ERR(led_gpio)) {dev_err(&pdev->dev, "Failed to get GPIO for led\n");return PTR_ERR(led_gpio);}/* 4.2 注册file_operations 	*/major = register_chrdev(0, "100ask_led", &led_drv);  /* /dev/led */led_class = class_create(THIS_MODULE, "100ask_led_class");if (IS_ERR(led_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "led");gpiod_put(led_gpio);return PTR_ERR(led_class);}device_create(led_class, NULL, MKDEV(major, 0), NULL, "100ask_led%d", 0); /* /dev/100ask_led0 */return 0;
}static int chip_demo_gpio_remove(struct platform_device *pdev)
{device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);unregister_chrdev(major, "100ask_led");gpiod_put(led_gpio);
}static const struct of_device_id ask100_leds[] = {{ .compatible = "100ask,leddrv" },{ },
};/* 1. 定义platform_driver */
static struct platform_driver chip_demo_gpio_driver = {.probe      = chip_demo_gpio_probe,.remove     = chip_demo_gpio_remove,.driver     = {.name   = "100ask_led",.of_match_table = ask100_leds,},
};/* 2. 在入口函数注册platform_driver */
static int __init led_init(void)
{int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = platform_driver_register(&chip_demo_gpio_driver); return err;
}/* 3. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函�? *     卸载platform_driver*/
static void __exit led_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);platform_driver_unregister(&chip_demo_gpio_driver);
}/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */module_init(led_init);
module_exit(led_exit);MODULE_LICENSE("GPL");

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

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

相关文章

比亚迪今年的薪资。。

大家或许已经对比亚迪在西安的宣讲会有所耳闻&#xff0c;那场面真的是座无虚席。如果你稍微迟到了一些&#xff0c;那么你可能只能在门外或是走廊听了。 事实上&#xff0c;许多人早早地抵达了&#xff0c;只要稍微晚到&#xff0c;就可能错过了室内的位置。 更令人震惊的是&…

HCIA数据通信——静态路由

之前的文章中我提到过静态路由&#xff1a; 数据通信——网络层&#xff08;路由器以及数据转发流程&#xff09;_路由器如何转发数据_咕噜跳的博客-CSDN博客这里只做一些简单描述。 路由器关注的是网络之间的通信。路由器以自身为中心&#xff0c;考虑的是如何将数据发送到目…

优维产品最佳实践第13期:如何避免拨测机自身网络问题?

受限于拨测节点自身的环境&#xff0c;单一节点的拨测结果可能并不能反映出监控实例的真实运行状态 本期EasyOps产品使用最佳实践&#xff0c;我们将为您揭晓&#xff1a; 如何基于多点决策配置拨测监控&#xff0c;以避免拨测机自身网络问题而误告警&#xff1f; 如何对指标…

Paddle炼丹炉炸了Unexpected BUS error encountered in DataLoader worker

Paddle训练报错&#xff0c;内存不足 python train.py -c config/ResNet_W18.yaml修改配置文件config/ResNet_W18.yaml # 原配置 loader:num_workers: 4use_shared_memory: True# 修改后 loader:num_workers: 2use_shared_memory: False

基于GB28181-2022实现web无插件播放H265视频

目前发布的GB28181-2022增加了对前端设备视频H265编码格式的支持&#xff0c;所以实现国标平台通过浏览器对H265视频流的无插件的解码播放将是未来的趋势。 目前大多的方案都是通过平台端把H265转码为H264&#xff0c;再推送到web前端进行解码播放&#xff0c;这种方式因为需要…

MAA连不上MUMU模拟器

之前一直能正常用&#xff0c;最近突然连接不上&#xff0c;最终发现是adb版本不同造成的&#xff0c;我系统变量的adb版本如下&#xff1a; MUMU自带adb版本如下&#xff1a; 解决办法&#xff1a; 把mumu的adb复制到系统变量路径下&#xff0c;或者把adb的系统变量删除

小红书协议算法最新版

如果您想通过学习来了解小红书的点赞、关注、私信等功能的实现&#xff0c;以下是一些一般性的思路和示例代码&#xff0c;供您学习参考&#xff1a; 1. 点赞功能&#xff1a; - 后端实现&#xff1a;在后端&#xff0c;您可以创建一个用于存储用户点赞信息的数据库表。对于每…

STM32-创建项目流程

一、基于STM官网得库进行开发 准备工作&#xff1a;下载STM库文件 1、创建项目文件夹 2、在keil 中new uVision project,然后选择刚刚创建得文件夹&#xff0c;在文件夹里面创建一个文件&#xff0c;用来存放这个项目&#xff0c;然后在文件夹里面&#xff0c;写个文件名&am…

基于机器视觉的银行卡识别系统 - opencv python 计算机竞赛

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的银行卡识别算法设计 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…

在基于亚马逊云科技的湖仓一体架构上构建数据血缘的探索和实践

背景介绍 随着大数据技术的进步&#xff0c;企业和组织越来越依赖数据驱动的决策。数据的质量、来源及其流动性因此显得非常关键。数据血缘分析为我们提供了一种追踪数据从起点到终点的方法&#xff0c;有助于理解数据如何被转换和消费&#xff0c;同时对数据治理和合规性起到关…

HarmonyOS(二)—— 初识ArkTS开发语言(上)之TypeScript入门

前言 Mozilla创造了JS&#xff0c;Microsoft创建了TS&#xff0c;而Huawei进一步推出了ArkTS。因此在学习使用ArkTS前&#xff0c;需要掌握基本的TS开发技能。 ArkTS介绍 ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript&#xff08;简称TS&#xff09;的基础上&am…

奇富科技引领大数据调度革命:高效、稳定、实时诊断

日前&#xff0c;在世界最大的开源基金会 Apache旗下最为活跃的项目之一DolphinScheduler组织的分享活动上&#xff0c;奇富科技的数据平台专家刘坤元应邀为国内外技术工作者献上一场题为《Apache DolphinScheduler在奇富科技的优化实践》的精彩分享&#xff0c;为大数据任务调…

历年网规上午真题笔记(2015年)

解析: 变更控制为“问题识别”——“问题分析与变更描述”——“变更分析与成本计算”——“变更实现”——“修改后的需求” 自动化工具能够帮助变更控制过程更有效地运作,能有效收集、存储、管理变更,工具应该具备的特征如下: 可定义变更请求中的数据可定义变更请求生命…

云原生环境下JAVA应用容器JVM内存如何配置?—— 筑梦之路

Docker环境下的JVM参数非定值配置 —— 筑梦之路_docker jvm设置-CSDN博客 之前简单地记录过一篇&#xff0c;这里在之前的基础上更加细化一下。 场景说明 使用Java开发且设置的JVM堆空间过小时&#xff0c;程序会出现系统内存不足OOM&#xff08;Out of Memory&#xff09;的…

基于SSM的餐饮掌上设备点餐系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

Java,面向对象,抽象类和抽象方法(abstract的使用)

关于抽象类和抽象方法的使用&#xff0c;以Person和student和Teacher为例&#xff0c;若Student类和Teacher继承于Person类&#xff0c;老师和学生都有Person的特征。在一个班级里&#xff0c;只需要创建老师和学生的实例&#xff0c;并不需要创建Person的实例。关于Person的方…

OpenAI将推出ChatGPT Plus会员新功能,有用户反馈将支持上传文件和多模态

&#x1f989; AI新闻 &#x1f680; OpenAI将推出ChatGPT Plus会员新功能&#xff0c;有用户反馈将支持上传文件和多模态 摘要&#xff1a;OpenAI为ChatGPT Plus会员推出了一些新功能&#xff0c;包括上传文件、处理文件和多模态支持。用户不再需要手动选择模式&#xff0c;…

学习使用php实现汉字验证码

学习使用php实现汉字验证码 <?php //开启session &#xff0c;方便验证 session_start(); //创建背景画布 $image imagecreatetruecolor(200, 60); $background imagecolorallocate($image, 255, 255, 255); imagefill($image, 0, 0, $background);//创建背景画布 for ($…

HBase理论与实践-基操与实践

基操 启动&#xff1a; ./bin/start-hbase.sh 连接 ./bin/hbase shell help命令 输入 help 然后 <RETURN> 可以看到一列shell命令。这里的帮助很详细&#xff0c;要注意的是表名&#xff0c;行和列需要加引号。 建表&#xff0c;查看表&#xff0c;插入数据&#…

Android开发知识学习——Kotlin进阶

文章目录 次级构造主构造器init 代码块构造属性data class相等性解构Elvis 操作符when 操作符operatorLambda循环infix 函数嵌套函数注解使用处目标函数简化函数参数默认值扩展函数类型内联函数部分禁用用内联具体化的类型参数抽象属性委托属性委托类委托 Kotlin 标准函数课后题…