【驱动开发】注册字符设备使用gpio设备树节点控制led三盏灯的亮灭
注册字符设备使用gpio设备树节点控制led三盏灯的亮灭
设备树:

头文件:
#ifndef __HEAD_H__
#define __HEAD_H__
typedef struct
{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR;
} gpio_t;
#define PHY_LED1_ADDR 0X50006000
#define PHY_LED2_ADDR 0X50007000
#define PHY_LED3_ADDR 0X50006000
#define PHY_RCC_ADDR 0X50000A28
// 构建开灯关灯的功能码
#define LED_ON _IOW('l', 1,int)
#define LED_OFF _IOW('l', 0,int)#endif
驱动程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/kdev_t.h>
#include "head.h"
struct class *cls;
struct device *dev;
struct resource *res;
unsigned int irqno;
struct device_node *dnode;
struct gpio_desc *gpiono1;
struct gpio_desc *gpiono2;
struct gpio_desc *gpiono3;
struct cdev *cdev;
unsigned int major = 0;
unsigned int minor = 0;
dev_t devno;
int mycdev_open(struct inode *inode, struct file *file)
{unsigned int min = MINOR(inode->i_rdev); // 获取打开的文件的次设备号file->private_data = (void *)min;printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
ssize_t mycdev_read(struct file *file, char __user *user, size_t size, loff_t *lof)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
ssize_t mycdev_write(struct file *file, const char __user *user, size_t size, loff_t *lof)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int min = (int)file->private_data; // 获取文件的次设备号switch (min){case 0: // LED1switch (cmd){case LED_ON: // 开灯gpiod_set_value(gpiono1, 1);break;case LED_OFF: // 关灯gpiod_set_value(gpiono1, 0);break;}break;case 1: // LED2switch (cmd){case LED_ON: // 开灯gpiod_set_value(gpiono2, 1);break;case LED_OFF: // 关灯gpiod_set_value(gpiono2, 0);break;}break;case 2: // LED3switch (cmd){case LED_ON: // 开灯gpiod_set_value(gpiono3, 1);break;case LED_OFF: // 关灯gpiod_set_value(gpiono3, 0);break;}break;}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
struct file_operations fops = {.open = mycdev_open,.read = mycdev_read,.write = mycdev_write,.release = mycdev_close,.unlocked_ioctl = mycdev_ioctl,
};
int pdrv_probe(struct platform_device *pdev) // 当驱动和设备匹配成功后执行
{int ret,// 1.实例化字符设备驱动对象cdev = cdev_alloc();if (cdev == NULL){printk("申请字符设备驱动对象空间失败\n");ret = -EFAULT;goto OUT1;}printk("申请字符设备驱动对象空间成功\n");// 2.部分初始化字符设备驱动对象cdev_init(cdev, &fops);// 3.申请设备号if (major == 0) // 动态申请设备号{ret = alloc_chrdev_region(&devno, minor, 3, "mycdev");if (ret){printk("动态申请设备号失败\n");goto OUT2;}major = MAJOR(devno);minor = MINOR(devno);}else // 静态指定设备号{ret = register_chrdev_region(devno, 3, "mycdev");if (ret){printk("静态设备号失败\n");goto OUT2;}}printk("设备号申请成功\n");// 4.将字符设备驱动对象注册进内核ret = cdev_add(cdev, MKDEV(major, minor), 3);if (ret){printk("注册字符设备驱动失败\n");goto OUT3;}printk("注册字符设备驱动成功\n");// 5.自动创建设备节点cls = class_create(THIS_MODULE, "mycdev");if (IS_ERR(cls)){printk("向上提交目录失败\n");ret = -PTR_ERR(cls);goto OUT4;}printk("向上提交目录成功\n");// 向上提交设备节点int i;for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mycdev%d", i);if (IS_ERR(dev)){printk("向上提交设备信息失败\n");ret = PTR_ERR(dev);goto OUT5;}}printk("自动创建设备节点成功\n");res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res == NULL){printk("解析资源失败%d\n", __LINE__);return -ENOMEM;}irqno = platform_get_irq(pdev, 0);if (irqno < 0){printk("解析资源失败%d\n", __LINE__);return -ENOMEM;}printk("mem:%x irq:%d\n", res->start, irqno);// 使用gpio驱动dnode = of_find_node_by_path("/myplatform");if (dnode == NULL){printk("解析设备树节点失败\n");return -ENXIO;}// 解析出GPIO编号并申请gpiono1 = gpiod_get_from_of_node(pdev->dev.of_node, "led1-gpio", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono1)){printk("GPIO信息解析失败\n");return -PTR_ERR(gpiono1);}gpiono2 = gpiod_get_from_of_node(pdev->dev.of_node, "led2-gpio", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono2)){printk("GPIO信息解析失败\n");return -PTR_ERR(gpiono2);}gpiono3 = gpiod_get_from_of_node(pdev->dev.of_node, "led3-gpio", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono3)){printk("GPIO信息解析失败\n");return -PTR_ERR(gpiono3);}/*gpiod_set_value(gpiono1,1);gpiod_set_value(gpiono2,1);gpiod_set_value(gpiono3,1);*/printk("GPIO信息解析成功\n");return 0;
OUT5:// 释放提交成功的设备节点信息for (i--; i >= 0; i--){device_destroy(cls, MKDEV(major, i));}// 销毁目录class_destroy(cls);
OUT4:cdev_del(cdev);
OUT3:unregister_chrdev_region(MKDEV(major, minor), 3);
OUT2:kfree(cdev);
OUT1:return ret;
}
int pdrv_remove(struct platform_device *pdev) // 当设备和驱动分离时执行
{// 释放GPIO信息gpiod_put(gpiono1);gpiod_put(gpiono2);gpiod_put(gpiono3);// 销毁节点信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录class_destroy(cls);// 注销驱动unregister_chrdev(major, "mychrdev");return 0;
}
// 构建设备树匹配表
struct of_device_id oftable[] = {{.compatible = "hqyj,myplatform",},{.compatible = "hqyj,myplatform1",},{}, // 防止数组越界
};
// 1.分配驱动信息对象
struct platform_driver pdrv = {.probe = pdrv_probe,.remove = pdrv_remove,.driver = {.name = "bbbbb", // 驱动名.of_match_table = oftable,},
};
// 一键注册宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");
应用程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "head.h"int main(int argc, char const *argv[])
{int a, b;int fd;while (1){// 从中断获取我们想实现的功能功能printf("请选择要控制的灯:0-LED1,1-LED2,2-LED3\n");scanf("%d", &a);switch (a){case 1:fd = open("/dev/mycdev0", O_RDWR);break;case 2:fd = open("/dev/mycdev1", O_RDWR);break;case 3:fd = open("/dev/mycdev2", O_RDWR);break;}if (fd < 0){printf("打开设备文件失败\n");return -1;}printf("打开设备文件成功\n");printf("请输入想要实现的功能 ");printf("0(关灯)1(开灯)\n");printf("请输入>>>");scanf("%d", &b);switch (b){case 1:ioctl(fd, LED_ON, &b);break;case 0:ioctl(fd, LED_OFF, &b);break;}}close(fd);return 0;
}


相关文章:
【驱动开发】注册字符设备使用gpio设备树节点控制led三盏灯的亮灭
注册字符设备使用gpio设备树节点控制led三盏灯的亮灭 设备树: 头文件: #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int OD…...
面向制造企业的持续发展,2023数字化工单管理系统创新篇章-亿发
面向制造企业的持续发展,2023数字化工单管理系统开创新篇章-亿发 随着制造业的持续发展,运维工单管理日益成为关键环节,它设计客户管理、设备维护、服务商合作等多个业务领域,对运营效率和服务质量有着重要影响。然而,…...
mysql 元数据锁 MDL读锁与MDL写锁
事务一开启事务 begin; select * from tablename;--相当于加了MDL读锁 此时事务2执行alter table tablename add ... --会发生修改阻塞 commit; --提交事务 释放MDL读锁 此时事务二修改成功 如果事务一执行做dml操作,操作期间将加MDL写锁...
批量预处理哨兵2影像
批量预处理哨兵2影像 最近下载70多景哨兵2影像,平均每个影像在cmd中处理时间都需要半个小时。算下来我一景一景手动处理需要37个小时左右,每天在电脑前待8个小时也要4天多,很浪费时间。如果能够批处理,不需要我手动做的话&#x…...
Unity地面交互效果——2、动态法线贴图实现轨迹效果
Unity引擎动态法线贴图制作球滚动轨迹 大家好,我是阿赵。 之前说了一个使用局部UV采样来实现轨迹的方法。这一篇在之前的基础上,使用法线贴图进行凹凸轨迹的绘制。 一、实现的目标 先来回顾一下,上一篇最终我们已经绘制了一个轨迹的贴图…...
视频剪辑达人教您:如何运用嵌套合并技巧制作固定片尾
在视频剪辑的过程中,嵌套合并技巧是一种非常实用的技术,可以帮助您将多个素材叠加在一起,制作出更加丰富多彩的视频。本文将由视频剪辑达人为您详细介绍如何运用云炫AI智剪嵌套合并技巧制作固定片尾,让您的视频剪辑水平更上一层楼…...
【腾讯云 TDSQL-C Serverless 产品体验】TDSQL-C MySQL Serverless最佳实践
一、引言: 随着云计算技术的不断发展,越来越多的企业开始选择将自己的数据库部署在云上,以更好了的支持企业数字化转型以及业务创新,在这个过程中,很多客户会遇到这样一个问题,业务会存在高峰期和低谷期&a…...
SQLyog连接数据库报plugin caching_sha2_password could not be loaded......解决方案
问题描述 问题分析 因为MySQL新版默认使用caching_sha2_password作为身份验证的插件,而旧版本使用的是mysql_native_password。当出现plugin caching_sha2_password could not be loaded报错,我们更换为旧版本 如何解决 先使用cmd命令登录MySQL&a…...
linux应急排查
常用命令 查看登录用户和活动 whoami:显示当前登录用户的用户名。 w:显示当前登录到系统上的用户列表和他们正在执行的命令。 last:显示最近登录到系统的用户列表、登录时间和来源IP地址。 ps aux:列出当前正在运行的所有进程&…...
Apache POI及easyExcel读取及写入excel文件
目录 1.excel 2.使用场景 3.Apache POI 4.easyExcel 5.总结 1.excel excel分为两版,03版和07版。 03版的后缀为xls,最大有65536行。 07版的后缀为xlsx,最大行数没有限制。 2.使用场景 将用户信息导出到excel表格中。 将excel中的数…...
为什么写作
1记录生活,表达自己的想法和情感,提高沟通能力。 2年轻的时候就有写作的意愿,一直未动笔。 3想突破自己看看自己能写到什么程度。锻炼自己更好组织思路,提高逻辑思维能力。 4给自己的生活增添一些爱好,更好地理解和…...
python基于VGG19实现图像风格迁移
目录 1、原理 2、代码实现 1、原理 图像风格迁移是一种将一张图片的内容与另一张图片的风格进行合成的技术。 风格(style)是指图像中不同空间尺度的纹理、颜色和视觉图案,内容(content)是指图像的高级宏观结构。 实…...
BoredHackerBlog: Cloud AV RT日记
目录 信息搜集 WEB漏洞攻击 拿shell 信息搜集 首先ifconfig查看自己IP, netdiscover查看同网段下主机 第三个应该是目标靶机。用nmap查看靶机开放端口: 开放22和8080,看看8080开的啥服务 WEB漏洞攻击 看到让我们输入邀请码。有输入框的第…...
数据结构之“初窥门径”
目录 前言: 一,数据结构起源 二,基本概念和术语 2.1数据 2.2数据元素 2.3数据项 2.4数据对象 2.5数据结构 三,逻辑结构与物理结构 3.1逻辑结构 3.1.1集合结构 3.1.2线性结构 3.1.3树形结构 3.1.4图形结构 3.2物理结…...
css:transform实现平移、旋转、缩放、倾斜元素
目录 文档语法示例旋转元素 transform-rotate旋转过渡旋转动画 参考文章 文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform 语法 /* Keyword values */ transform: none;/* Function values */ transform: matrix(1, 2, 3, 4, 5, 6); transform: translate…...
如何理解AutoGPT
AutoGPT和GPT-4都是OpenAI公司的产品。AutoGPT是一个实验性开源应用程序,展示了GPT-4语言模型的能力。GPT-4是OpenAI研发的人工智能语言模型。 AutoGPT在GitHub主页上有151k星(151k星代表了151,000个用户点赞了该项目),AutoGPT获…...
【网络知识必知必会】聊聊网络层IP协议
文章目录 前言IP 协议格式总结 前言 在之前的博文中, 我们聊过了传输层中的两个重点协议 TCP 和 UDP, 本文我们再来聊聊网络层中的一个协议IP, 简单认识一下 IP 协议格式. IP 协议与 TCP 协议的复杂度也不妨多让, 不过我们在这里只是简单的聊一聊 IP 协议的报文格式就行, 毕竟…...
66. 加一
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 示例 1: 输入: digits …...
逻辑(css3)_强制不换行
需求 如上图做一个跑马灯数据,时间、地点、姓名、提示文本字数都不是固定的。 逻辑思想 个人想法是给四个文本均设置宽度,不然会出现不能左对齐的现象。 此时四个文本均左对齐, 垂直排列样式也比较好看,但是出现一个缺点&#…...
营收净利双降、股价下跌四成,敷尔佳带伤闯关“双11”
今年双11预售已经开启,敷尔佳在天猫、抖音等电商平台火热营销;营销热业绩冷,敷尔佳的三季报不及预期。 10月23日,哈尔滨敷尔佳科技发展有限公司(下称“敷尔佳”,301371SZ)公布2023年三季报,其三季度营收净…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
