Linux驱动入门实验班——LED驱动(附百问网视频链接)

目录

一、确定引脚编号

二、编写思路

2.1驱动层

2.2应用层

三、源码

四、实现

课程链接


一、确定引脚编号

首先,可以在开发板上执行如下命令查看已经在使用的GPIO状态:

cat /sys/kernel/debug/gpio

可以看到每个gpio都有对应的编号,如何查看自己想要的设备对应的gpio编号呢?

最简单的就是可以通过查看原理图 :

我所使用的开发板时IMX6ULL,所以下面也是IMX6ULL的开发板原理图上截取出来的

通过原理图我们可以观察到LED所在的引脚为GPIO5_3,意思是第五组中的第三个

根据上方我们用cat命令查看到的GPIO状态,可知一组GPIO为0-31,也就是三十二个。

GPIO1:0~31

GPIO2:32~63

GPIO5:4 x 32 

GPIO5_3 : 4 x 32 + 3

可知LED引脚为 32 x 5 + 3 = 131

得出来引脚编号,就可以进行代码实现了。 

二、编写思路

2.1驱动层

1.先构造file_operations结构体。

static struct file_operations led_drv = {.owner = THIS_MOUDLE,.read = led_drv_read,.write = led_drv_write,
};

2.实现write和read函数

根据自己构造出来的的file_operations结构体,去实现具体的函数。

使用到的函数

  • opy_to_user()
  • copy_from_user()
  • gpio_set_value
  • gpio_get_value

在上一篇文章有具体介绍这篇文章所使用到的函数的作用和使用方法。

3.编写入口函数

用到的函数

  • gpio_request
  • gpio_direction_output
  • register_chrdev
  • class_create
  • device_create

4.编写出口函数

  • device_destroy
  • class_destroy
  • unregister_chrdev
  • gpio_free

5.声明出口函数和入口函数,声明描述内核模块的许可权限 

  • module_init
  • module_exit
  • MODULE_LICENSE("GPL");

2.2应用层

根据传入参数的个数和值,判断用户想对那个引脚进行什么操作 

实现选择控制LED亮灭,可读取GPIO电平状态

三、源码

led_drv.c

#include "asm-generic/errno-base.h"
#include "asm-generic/gpio.h"
#include "asm/uaccess.h"
#include <linux/module.h>
#include <linux/poll.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/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>struct gpio_desc {int gpio;int irq;char *name;
};static struct gpio_desc gpios[2] = 
{{131, 0, "led0"},
};static int major = 0;
static struct class *led_class;static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{char kernel_buf[2];int err;if(size != 2){return -EINVAL;}err = copy_from_user(kernel_buf, buf, 1);if(kernel_buf[0] >= (sizeof(gpios)/sizeof(gpios[0]))){return -EINVAL;}kernel_buf[1] = gpio_get_value(gpios[kernel_buf[0]].gpio);err = copy_to_user(buf, kernel_buf, 2);return 2;
}static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{char kernel_buf[2];int err;if (size != 2){return -EINVAL;}err = copy_from_user(kernel_buf, buf, 1);if (kernel_buf[0] >= (sizeof(gpios)/sizeof(gpios[0]))){return -EINVAL;}gpio_set_value(gpios[kernel_buf[0]].gpio,kernel_buf[1]);return 2;a
}static struct file_operations led_drv = {.owner = THIS_MODULE,.read = led_drv_read,.write = led_drv_write,
};static int __init led_drv_init(void)
{int err;int i;int count = sizeof(gpios)/sizeof(gpios[0]);for (i = 0; i < count; i++){err = gpio_request(gpios[i].gpio, gpios[i].name);if (err < 0) {printk("can not request gpio %s %d\n", gpios[i].name, gpios[i].gpio);return -ENODEV;}gpio_direction_output(gpios[i].gpio, 1);}/* 注册file_operations结构体 */major = register_chrdev(0, "led_drv",&led_drv);led_class = class_create(THIS_MODULE, "drv_class");if (IS_ERR(led_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "led_class");return PTR_ERR(led_class);}device_create(led_class, NULL, MKDEV(major, 0), NULL, "led_drv");return 0;
}static void __exit led_drv_exit(void)
{int i;int count = sizeof(gpios)/sizeof(gpios[0]);device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);unregister_chrdev(major, "led_drv");for(i = 0; i< count; i++){gpio_free(gpios[i].gpio);}
}module_init(led_drv_init);
module_exit(led_drv_exit);MODULE_LICENSE("GPL");

led_drv_test.c

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>int main(int argc, char **argv)
{int ret;int fd;char buf[2];if (argc < 2){printf("Usage : %s <0> [on|off]", argv[0]);return -1;}fd = open("/dev/led_drv", O_RDWR);if (fd == -1){printf("can not open file /dev/100ask_led\n");return -1;}if (argc == 3){buf[0] = strtol(argv[1],NULL, buf[0]);if(strcmp(argv[2],"on") == 0){buf[1] = 0;}else{buf[1] = 1;}ret = write(fd, buf, 2);}else{buf[0] = strtol(argv[1], NULL, 0);ret = read(fd, buf, 2);if (ret == 2){printf("led %d status is %s\n", buf[0], buf[1] == 0 ? "on" : "off");}}close(fd);return 0;
}

四、实现

在开发板上执行以下命令,将生成的.ko文件装载到内核

insmod led_drv.ko

课程链接

36_模板1实战_LED驱动上机_STM32MP157_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1XK411D7wK/?p=37&spm_id_from=pageDriver&vd_source=3a9afee9fda50350a1c881b4325e007d

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

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

相关文章

火语言RPA--火语言界面应用多窗体详解

多窗体 界面应用建立时默认加载一个窗体&#xff0c;若是程序运行时需要多个窗体配合&#xff0c;在通常情况下&#xff0c;您可将多窗体绑定在UI控件事件中&#xff0c;由界面交互来打开多窗体。 本章将介绍下如何建立多窗体以及在应用中如何运用多窗体完成多种场景的设置。 …

源代码防泄密怎么做?最好用的12款源代码加密软件推荐

源代码是企业的核心资产之一&#xff0c;其安全性直接关系到产品的竞争力和市场地位。防止源代码泄密是企业信息安全中的重中之重&#xff0c;本文将介绍几种有效的源代码防泄密方法&#xff0c;并推荐12款优秀的源代码加密软件。 1. 代码审查与权限管理 通过严格的代码审查流…

【MySQL】用户管理——用户、用户信息、创建用户、删除用户、修改用户密码、数据库的权限、给用户权限、回收权限

文章目录 MySQL1. 用户管理1.1 用户1.1.1 用户信息1.1.2 创建用户1.1.3 删除用户1.1.4 修改用户密码 1.2 数据库的权限1.2.1 给用户权限1.2.2 回收权限 MySQL 1. 用户管理 为什么MySQL要引入用户管理&#xff1f; 如果我们只能使用root用户&#xff0c;这样存在安全隐患。因为r…

[C++][opencv]基于opencv实现photoshop算法可选颜色调整

【测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心实现代码】 SelectiveColor.hpp #ifndef OPENCV2_PS_SELECTIVECOLOR_HPP_ #define OPENCV2_PS_SELECTIVECOLOR_HPP_#include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "…

Mariadb数据库本机无密码登录的问题解决

Mariadb数据库本机无密码登录的问题解决 安装了mariadb后&#xff0c;发现Mariadb本机无密码才能登录 百度了很多文章&#xff0c;发现很多人是因为root的plugin设置的值不正确导致的&#xff0c;unix_socket可以不需要密码&#xff0c;mysql_native_password 是正常的。 解…

NLP_情感分类_预训练加微调方案

文章目录 项目背景代码导包一些模型以及训练的参数设置定义dataset定义模型读取数据声明训练及测试数据集将定义模型实例化打印模型结构模型训练测试集效果 同类型项目 项目背景 项目的目的&#xff0c;是为了对情感评论数据集进行预测打标。在训练之前&#xff0c;需要对数据…

Datawhale X 魔搭 AI夏令营 第四期魔搭-AIGC文生图方向Task2笔记

了解一下 AI生图技术 的能力&局限 对所有人来说&#xff0c;定期关注AI生图的最新能力情况都十分重要&#xff1a; 对于普通人来说&#xff0c;可以避免被常见的AI生图场景欺骗&#xff0c;偶尔也可以通过相关工具绘图 对于创作者来说&#xff0c;通过AI生图的工具可以快速…

全球 30 万台游戏服务器的 PlayFlow Cloud 如何通过 DigitalOcean 实现动态扩展

“我在 DigitalOcean 上首次接触了 Kubernetes。设置 Kubernetes 集群非常简单&#xff0c;使我能够轻松自动化扩展我们的游戏服务器。”——Haseeb Sheikh&#xff0c;PlayFlow Cloud 创始人兼首席执行官 PlayFlow Cloud 是由 Haseeb Sheikh 创立的&#xff0c;旨在通过简化游…

13 Listbox 组件

13 Listbox 组件 Tkinter 的 Listbox 组件是一个用于显示列表项的控件&#xff0c;用户可以从中选择一个或多个项目。以下是对 Listbox 组件的详细说明和一个使用案例。 Listbox 组件属性 基本属性 width: 控件的宽度&#xff0c;通常以字符数为单位。height: 控件的高度&a…

Docker 网络代理配置及防火墙设置指南

Docker 网络代理配置及防火墙设置指南 背景 在某些环境中&#xff0c;服务器无法直接访问外网&#xff0c;需要通过网络代理进行连接。虽然我们通常会在 /etc/environment 或 /etc/profile 等系统配置文件中直接配置代理&#xff0c;但 Docker 命令无法使用这些配置。例如&am…

Midjourney提示词——《环太平洋》机甲专场(附公式)

前言 本篇为大家带来《环太平洋》的机甲提示词&#xff0c;文末附公式&#xff0c;有需要的可以直接复制点击下方阅读原文尝试使用哦~ 1、危险流浪者 Gypsy Danger, standing tall and heroic, dramatic lighting highlighting the metal plates, deep blue and silver color…

[图解]需要≠需求-《分析模式》漫谈

1 00:00:00,760 --> 00:00:02,910 今天的《分析模式》漫谈 2 00:00:02,920 --> 00:00:04,180 我们来说一下 3 00:00:04,490 --> 00:00:06,490 需要不等于需求 4 00:00:10,490 --> 00:00:11,760 还是第一章 5 00:00:13,120 --> 00:00:15,020 这里 6 00:00:1…

双胞胎命名有哪些特别之处?如何体现两者之间的联系与区别?

双胞胎命名艺术探秘 问题&#xff1a; 双胞胎命名有哪些特别之处&#xff1f;如何体现两者之间的联系与区别&#xff1f; 起尔网-免费取名|大师起名|宝宝起名|新生儿取名|男孩女孩在线起名姓名测试评分网起尔网-免费在线宝宝起名|新生儿取名|男孩女孩在线起名网&#xff0c;龙…

数据结构(学习)2024.8.6(顺序表)

今天开始学习数据结构的相关知识&#xff0c;大概分为了解数据结构、算法&#xff1b;学习线性表&#xff1a;顺序表、链表、栈、队列的相关知识和树&#xff1a;二叉树、遍历、创建&#xff0c;查询方法、排序方式等。 目录 一、数据结构 数据 逻辑结构 1.线性结构 2.树…

Ubuntu20.04 源码安装 OMPL 与 Moveit

文章目录 一、源码安装OMPL1.1 先检查是否已安装二进制 ompl1.2 若已经提前安装二进制&#xff0c;需先行卸载1.3 OMPL官网安装教程 二、源码安装 moveit2.1 先检查是否已安装二进制Moveit2.2 源码安装 Moveit2.2.1、更新软件包2.2.2、安装依赖2.2.3、创建Moveit工作空间2.2.4…

<Qt> 系统 - 文件

目录 一、Qt文件概述 二、输入输出设备类 三、文件读写类 四、文件和目录信息类 一、Qt文件概述 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库&#xff0c;提供了跨平台的文件操作能力。Qt 提供了很多关于文件的类&#xff0c;通过这些类能够对文件系统进行操…

Openlayers6 图形绘制和修改功能(结合React)

Openlayers常用的API了解的差不多了&#xff0c;就开始进入实战了&#xff0c;首先从绘制基本的图形开始&#xff0c;这里主要介绍一下绘制圆形、矩形和多边形。 通过使用openlayers的ol.interaction.Draw和ol.interaction.Modify模块实现地图上绘制圆形、矩形、多边形并修改编…

mesh格式转换:glb转ply——使用Blender烘焙贴图到顶点色

1. 导入glb文件 选择shading后&#xff0c;选中物体&#xff0c;就能看到下面的节点树。 2. 创建顶点颜色 这个时候我们可以看到模型的顶点颜色是纯白色的。 2. 将贴图付给材质 原来&#xff1a; 现在&#xff1a; 3. 切换渲染器并烘焙顶点颜色 第三行选择CPU渲染或者GPU…

论文阅读:一种基于凸规划的高效有向最密子图发现方法 | SIGMOD 2022

论文概述 这篇论文的主题是研究如何在有向图中找到密度最高的子图&#xff0c;这个问题被称为有向最密子图&#xff08;Directed Densest Subgraph, DDS&#xff09;问题。该问题在许多应用中非常重要&#xff0c;如社交网络分析、社区发现、假粉丝检测等。论文提出了一种基于…

AI for reading ML paper

心流 心流 Kimi Kimi Humata Humata Bytez Bytez Chatgpt4 scholar 学术版chatgpt4&#xff0c;需要充值&#xff1b; 还有更多AI工具等待你发现&#xff1b;