驱动 - 20230829
练习
基于platform实现

在根节点下,增加设备树
myplatform {compatible="hqyj,myplatform";interrupts-extended=<&gpiof 9 0>, <&gpiof 7 0>, <&gpiof 8 0>;led1-gpio=<&gpioe 10 0>;reg=<0x12345678 59>;};
驱动代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>// 中断
struct device_node *dnode;
unsigned int key_irqno;
struct gpio_desc *gpiono;
// 字符设备驱动
int major;
// 自动创建设备节点
struct class *cls;
struct device *dev;struct resource *res;int number = 0;
unsigned int condition = 0;
wait_queue_head_t wq_head; // 等待队列头// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{int ret;char kbuf[128] = {0};sprintf(kbuf, "number = %d", number);if (file->f_flags & O_NONBLOCK){// 非阻塞return -EINVAL;}else{// 阻塞ret = wait_event_interruptible(wq_head, condition);if (ret < 0){printk("receive signal.... \n");return ret;}}// 拷贝数据到用户空间ret = copy_to_user(ubuf, kbuf, size);if (ret){printk("copy_to_user err \n");return -EIO;}// condition清零condition = 0;return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{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,
};irqreturn_t key_handler(int irq, void *dev)
{if (number == 0){number = 1;}else{number = 0;}gpiod_set_value(gpiono, number);condition = 1;wake_up_interruptible(&wq_head);return IRQ_HANDLED;
}// 封装probe函数和remove函数
int pdrv_probe(struct platform_device *pdev)
{printk("pdrv_probe --------------------------- \n");int ret;/*** 1. 注册设备驱动*/major = register_chrdev(0, "mychrdev", &fops);if (major < 0){printk("字符设备驱动注册失败 \n");return major;}printk("字符设备驱动注册成功\n");/*** 2. 自动创建设备节点*/// 向上提交目录信息cls = class_create(THIS_MODULE, "mycdev");if (IS_ERR(cls)){printk("向上提交目录信息失败\n");return -PTR_ERR(cls);}printk("向上提交目录信息成功\n");// 向上提交设备信息dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycdev0");if (IS_ERR(dev)){printk("向上提交设备节点失败\n");return -PTR_ERR(cls);}// 3. 初始化等待队列头init_waitqueue_head(&wq_head);// 获取MEM类型的资源res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res == NULL){printk("获取MEM类型资源失败\n");return -ENXIO;}/*** 中断*/// 获取软中断号key_irqno = platform_get_irq(pdev, 0);if (key_irqno < 0) {printk("获取软中断号失败 \n");return -ENXIO;}printk("获取软中断号成功 \n");// 注册中断ret = request_irq(key_irqno, key_handler, IRQF_TRIGGER_FALLING, "key1", NULL);if (ret < 0){printk("注册中断失败\n");return -1;}printk("注册中断成功\n");/*** LED灯*/// 获取gpio编号gpiono=gpiod_get_from_of_node(pdev->dev.of_node,"led1-gpio",0,GPIOD_OUT_HIGH,NULL);if(IS_ERR(gpiono)){printk("解析gpio信息失败\n");return -PTR_ERR(gpiono);}printk("解析gpio编号成功\n");return 0;
}
int pdrv_remove(struct platform_device *pdev)
{free_irq(key_irqno, NULL);gpiod_set_value(gpiono, 0);gpiod_put(gpiono);device_destroy(cls, MKDEV(major, 0));class_destroy(cls);unregister_chrdev(major, "mychrdev");printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}// 构建设备树匹配表
struct of_device_id oftable[] = {{.compatible="hqyj,myplatform",},{},
};// 分配驱动信息对象并初始化
struct platform_driver pdrv = {.probe = pdrv_probe,.remove = pdrv_remove,.driver = {.name="aaaaa",.of_match_table = oftable,},
};module_platform_driver(pdrv);MODULE_LICENSE("GPL");
应用层代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <pthread.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/epoll.h>int main(int argc, const char* argv[])
{int fd;char buf[128];if ((fd = open("/dev/mycdev0", O_RDWR)) == -1) {perror("open error");exit(EXIT_FAILURE);}while (1) {bzero(buf, sizeof(buf));read(fd, buf, sizeof(buf));printf("status = %s\n", buf);}close(fd);return 0;
}
效果展示

相关文章:
驱动 - 20230829
练习 基于platform实现 在根节点下,增加设备树 myplatform {compatible"hqyj,myplatform";interrupts-extended<&gpiof 9 0>, <&gpiof 7 0>, <&gpiof 8 0>;led1-gpio<&gpioe 10 0>;reg<0x12345678 59>;}…...
数组(个人学习笔记黑马学习)
一维数组 1、定义方式 #include <iostream> using namespace std;int main() {//三种定义方式//1.int arr[5];arr[0] 10;arr[1] 20;arr[2] 30;arr[3] 40;arr[4] 50;//访问数据元素/*cout << arr[0] << endl;cout << arr[1] << endl;cout &l…...
layui表格事件分析实例
在 layui 的表格组件中,区分表头事件和行内事件是通过事件类型(toolbar 和 tool)以及 lay-filter 值来实现的。 我们有一个表格,其中有一个工具栏按钮和操作按钮。我们将使用 layui 的 table 组件来处理这些事件。 HTML 结构&…...
Android NDK JNI与Java的相互调用
一、Jni调用Java代码 jni可以调用java中的方法和java中的成员变量,因此JNIEnv定义了一系列的方法来帮助我们调用java的方法和成员变量。 以上就是jni调用java类的大部分方法,如果是静态的成员变量和静态方法,可以使用***GetStaticMethodID、CallStaticObjectMethod等***。就…...
装备制造企业如何执行精益管理?
导 读 ( 文/ 2358 ) 精益管理是一种以提高效率、降低成本和优化流程为目标的管理方法。装备制造行业具备人工参与度高,产成品价值高,质量要求高的特点。 在装备制造企业中实施精益管理可以帮助企业提高竞争力、提升生产效率并提供高质量的产品。本文将…...
PHP8中自定义函数-PHP8知识详解
1、什么是函数? 函数,在英文中的单词是function,这个词语有功能的意思,也就是说,使用函数就是在编程的过程中,实现一定的功能。即函数就是实现一定功能的一段特定代码。 在前面的教学中,我们已…...
虚拟化技术:云计算发展的核心驱动力
文章目录 虚拟化技术的概念和作用虚拟化技术的优势虚拟化技术对未来发展的影响结论 🎉欢迎来到AIGC人工智能专栏~虚拟化技术:云计算发展的核心驱动力 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系…...
光伏+旅游景区
传统化石燃料可开发量逐渐减少,并且对环境造成的危害日益突出。全世界都把目光投向了可再生能源,希望可再生能源能够改变人类的能源结构。丰富的太阳能取之不尽、用之不竭,同时对环境没有影响,光伏发电是近些年来发展最快…...
手搓文本向量数据库(自然语言搜索生成模型)
import paddle import jieba import pandas as pd import numpy as np import os from glob import glob from multiprocessing import Process, Manager, freeze_supportfrom tqdm import tqdm# 首先 确定的是输出的时候一定要使用pd.to_pickle() pd.read_pickle() # 计算的时…...
EVO大赛是什么
价格是你所付出的东西,而价值是你得到的东西 EVO大赛是什么? “EVO”大赛全称“Evolution Championship Series”,是北美最高规格格斗游戏比赛,大赛正式更名后已经连续举办12年,是全世界最大规模的格斗游戏赛事。常见…...
linux中使用clash代理
本机环境:ubuntu16 安装代理工具(这里使用clash) 可以手动下载解压,下载地址:https://github.com/Dreamacro/clash 也可以直接使用命令行,演示如下: userlocalhost:~$ curl https://glados.r…...
Kafka3.0.0版本——Follower故障处理细节原理
目录 一、服务器信息二、服务器基本信息及相关概念2.1、服务器基本信息2.2、LEO的概念2.3、HW的概念 三、Follower故障处理细节 一、服务器信息 三台服务器 原始服务器名称原始服务器ip节点centos7虚拟机1192.168.136.27broker0centos7虚拟机2192.168.136.28broker1centos7虚拟…...
13.redis集群、主从复制、哨兵
1.redis主从复制 主从复制是指将一台redis服务器(主节点-master)的数据复制到其他的redis服务器(从节点-slave),默认每台redis服务器都是主节点,每个主节点可以有多个或没有从节点,但一个从节点…...
linux字符串处理
目录 1 C 截取字符串,截取两个子串中间的字符串2 获取该字符串后面的字符串用 strstr() 函数查找需要提取的特定字符串,然后通过指针运算获取该字符串后面的字符串用 strtok() 函数分割字符串,找到需要提取的特定字符串后,调用 strtok() 传入…...
Nginx入门——Nginx的docker版本和windows版本安装和使用 代理的概念 负载分配策略
目录 引出nginx是啥正向代理和反向代理正向代理反向代理 nginx的安装使用Docker版本的nginx安装下载创建挂载文件获取配置文件创建docker容器拷贝容器中的配置文件删除容器 创建运行容器开放端口进行代理和测试 Windows版本的使用反向代理多个端口运行日志查看启动关闭重启 负载…...
Zebec Protocol:模块化 L3 链 Nautilus Chain,深度拓展流支付体系
过去三十年间,全球金融科技领域已经成熟并迅速增长,主要归功于不同的数字支付媒介的出现。然而,由于交易延迟、高额转账费用等问题愈发突出,更高效、更安全、更易访问的支付系统成为新的刚需。 此前,咨询巨头麦肯锡的一…...
Oracle-rolling upgrade升级19c
前言: 本文主要描述Oracle11g升19c rolling upgrade升级测试,通过逻辑DGautoupgrade方式实现rolling upgrade,从而达到在较少停机时间内完成Oracle11g升级到19c的目标 升级介绍: 升级技术: rolling upgrade轮询升级,通过采用跨版…...
Spring IOC详解
Spring 笔记 官网:https://spring.io/ 核心功能:当你的项目启动的时候,自动的将当前项目的各种 Bean 都自动的注册到 Spring 容器中,然后在项目的其他地方,如果需要用到这些 Bean,直接去 Spring 容器中查…...
Unity——DOTween插件使用方法简介
缓动动画既是一种编程技术,也是一种动画的设计思路。从设计角度来看,可以有以下描述 事先设计很多基本的动画样式,如移动、缩放、旋转、变色和弹跳等。但这些动画都以抽象方式表示,一般封装为程序函数动画的参数可以在使用时指定&…...
数据库——Redis 单线程模型详解
文章目录 Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型 (Netty 的线程模型也基于 Reactor 模式,Reactor 模式不愧是高性能 IO 的基石),这套事件处理模型对应的是 Redis 中的文件事件处理器(file …...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...
CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found
Nginx1.24编译时,报LuaJIT2.x错误, configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...
Spring是如何实现无代理对象的循环依赖
无代理对象的循环依赖 什么是循环依赖解决方案实现方式测试验证 引入代理对象的影响创建代理对象问题分析 源码见:mini-spring 什么是循环依赖 循环依赖是指在对象创建过程中,两个或多个对象相互依赖,导致创建过程陷入死循环。以下通过一个简…...
Neo4j 完全指南:从入门到精通
第1章:Neo4j简介与图数据库基础 1.1 图数据库概述 传统关系型数据库与图数据库的对比图数据库的核心优势图数据库的应用场景 1.2 Neo4j的发展历史 Neo4j的起源与演进Neo4j的版本迭代Neo4j在图数据库领域的地位 1.3 图数据库的基本概念 节点(Node)与关系(Relat…...
