嵌入式:驱动开发 Day9
作业:通过platform总线驱动实现
a.应用程序通过阻塞的io模型来读取number变量的值
b.number是内核驱动中的一个变量
c.number的值随着按键按下而改变(按键中断) 例如number=0 按下按键number=1 ,再次按下按键number=0
d.在按下按键的时候需要同时将led1的状态取反
e.驱动中需要编写字符设备驱动
f.驱动中需要自动创建设备节点
g.这个驱动需要的所有设备信息放在设备树的同一个节点中
驱动程序:my_platform.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/wait.h>struct cdev *cdev;
unsigned int major = 0;
unsigned int minor = 0;
dev_t devno;
module_param(major, uint, 0664); //方便命令行传递major的值
struct class *cls;
struct device *dev;
struct resource *res;
unsigned int irqno;
struct gpio_desc *gpiono;
wait_queue_head_t wq_head; //定义一个等待队列头
unsigned int number = 0;
unsigned int condition = 0;//定义中断处理函数
irqreturn_t key_handler(int irq, void *dev)
{gpiod_set_value(gpiono, !gpiod_get_value(gpiono));if (number == 0){number = 1;condition = 1;wake_up_interruptible(&wq_head);}else{number = 0;condition = 1;wake_up_interruptible(&wq_head);}return IRQ_HANDLED;
}//封装操作方法
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;//判断IO方式if (file->f_flags & O_NONBLOCK) //非阻塞{}else{ //阻塞wait_event_interruptible(wq_head, condition); //先检查condition再将进程休眠}ret = copy_to_user(ubuf, &number, size);if (ret){printk("copy_to_user err\n");return -EIO;}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,
};//封装probe函数
int pdrv_probe(struct platform_device *pdev)
{//初始化等待队列init_waitqueue_head(&wq_head);int ret;//1.为字符设备驱动对象申请空间cdev = cdev_alloc();if (cdev == NULL){printk("申请字符设备驱动对象空间失败\n");ret = -EFAULT;goto out1;}printk("申请字符设备驱动对象空间成功\n");//2.初始化字符设备驱动对象cdev_init(cdev, &fops);printk("初始化字符设备驱动对象成功\n");//3.申请设备号if (major > 0) //静态指定设备号{ret = register_chrdev_region(MKDEV(major, minor), 3, "myled");if (ret){printk("静态申请设备号失败\n");goto out2;}}else if (major == 0){ //动态申请设备号ret = alloc_chrdev_region(&devno, minor, 3, "myled");if (ret){printk("动态申请设备号失败\n");goto out2;}major = MAJOR(devno); //获取主设备号minor = MINOR(devno); //获取次设备号}printk("申请设备号成功\n");//4.注册字符设备驱动对象ret = cdev_add(cdev, MKDEV(major, minor), 3);if (ret){printk("注册字符设备驱动对象失败\n");goto out3;}printk("注册字符设备驱动对象成功\n");//向上提交目录信息cls = class_create(THIS_MODULE, "myled");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, "myled%d", i);if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");ret = -PTR_ERR(dev);goto out5;}}printk("向上提交设备信息成功\n");//platform//获取MEM类型的资源res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res == NULL){printk("获取MEM类型资源失败\n");return -ENXIO;}//获取中断类型的资源irqno = platform_get_irq(pdev, 0);if (irqno < 0){printk("获取中断类型资源失败\n");return -ENXIO;}//设备树匹配成功后,设备树结点指针可以通过pdev->dev.of_node获取//基于设备树节点信息获取gpio_desc对象指针gpiono = gpiod_get_from_of_node(pdev->dev.of_node, "led1-gpio", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono)){printk("解析GPIO管脚信息失败\n");return -ENXIO;}printk("解析GPIO管脚信息成功\n");//注册按键中断ret = request_irq(irqno, key_handler, IRQF_TRIGGER_FALLING, "key_init", NULL);if (ret < 0){printk("注册按键%d中断失败\n", i);return ret;}printk("注册按键中断成功\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;
}//封装remove函数
int pdrv_remove(struct platform_device *pdev)
{//注销中断free_irq(irqno, NULL);//释放GPIO信息gpiod_put(gpiono);int i;//释放设备节点信息for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}//销毁目录class_destroy(cls);//注销字符设备驱动对象cdev_del(cdev);//释放设备号unregister_chrdev_region(MKDEV(major, minor), 3);//释放设备驱动对象空间kfree(cdev);return 0;
}//构建设备树匹配表
struct of_device_id oftable[] = {{.compatible = "hqyj,myplatform"},{}, //防止数组越界
};//定义platform驱动信息对象并初始化
struct platform_driver pdrv = {.probe = pdrv_probe,.remove = pdrv_remove,.driver = {.name = "bbbbb",.of_match_table = oftable, //用于设备树匹配},
};//一键注册platform宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");
应用程序:test.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
int main(){unsigned int number;int fd = open("/dev/myled0", O_RDWR);if(fd < 0){printf("设备文件打开失败\n");exit(-1);}while(1){read(fd, &number, sizeof(number));printf("number = %d\n", number);}close(fd);return 0;
}
实验现象:
相关文章:

嵌入式:驱动开发 Day9
作业:通过platform总线驱动实现 a.应用程序通过阻塞的io模型来读取number变量的值 b.number是内核驱动中的一个变量 c.number的值随着按键按下而改变(按键中断) 例如number0 按下按键number1 ,再次按下按键number0 d.在按下按键的时候需要同时…...

【ComfyUI】安装 之 window版
文章目录 序言步骤下载comfyUI配置大模型和vae下载依赖组件启动 生成图片解决办法 序言 由于stable diffusion web ui无法做到对流程进行控制,只是点击个生成按钮后,一切都交给AI来处理。但是用于生产生活是需要精细化对各个流程都要进行控制的。 故也…...

iMazing 2 .17.9最新官方中文版免费下载安装激活
iMazing 2 .17.9最新版是一款帮助用户管理IOS手机的应用程序,iMazing2最新版能力远超iTunes提供的终极的iOS设备管理器。IMazing与你的iOS设备(iPhone、 iPad或iPod)相连,使用起来非常的方便。作为苹果指定的iOS设备同步工具。 mazing什么意思 iMazing…...

Postman应用——Pre-request Script和Test Script脚本介绍
文章目录 Pre-request Script所在位置CollectionFolderRequest Test Script所在位置CollectionFolderRequest Pre-request Script(前置脚本):可以使用在Collection、Folder和Request中,并在Request请求之前执行,可用于…...

vue2中年份季度选择器(需要安装element)
调用 <!--父组件调用--><QuarterCom v-model"quart" clearable default-current/> 组件代码 <template><div><span style"margin-right: 10px">{{ label }}</span><markstyle"position:fixed;top:0;bottom:0…...

QT day5
数据库完成登入注册 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include<QDebug> #include<QPushButton> #include<QLineEdit> #include<QLabel> #include <QMainWindow> #include<QMessageBo…...

设计模式Java实战
文章目录 一、前置1.1 目的1.2 面向对象1.3 接口和抽象类 二、七大设计原则2.1 单一职责2.2 接口隔离原则2.3 依赖倒转原则2.4 里氏替换原则2.5 开闭原则2.6 不要重复原则2.7 迪米特最少知道法则 三、23种设计模式3.1创建型:创建对象3.1.1 单例模式定义最佳实践场景…...

外国固定资产管理系统功能有哪些
很多公司都在寻找提高自己资产管理效益的方法。为了满足这一要求,国外的固定资产管理系统已经发展成多种形式。以下是国外一些常见的固定资产管理系统的特点:自动化和智能化:许多现代固定资产管理系统采用自动化和数字化技术,以简化流程,减少…...

Postman应用——控制台调试
当你在测试脚本中遇到错误或意外行为时,Postman控制台可以帮助你识别,通过将console.log调试语句与你的测试断言相结合,你可以检查http请求和响应的内容,以及变量之类的。 通常可以使用控制台日志来标记代码执行,有时…...

如何制作思维导图?
思维导图是一种非常有用的工具,可以被广泛应用于不同领域的人群。以下是一些常见的使用人群:学生、教育工作人员、各领域的专业人员,法律、商业、医学等等,创作者、艺术家、个人自我成长管理。 由此可见,思维导图可以做…...

【力扣每日一题】2023.9.21 收集树中金币
目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们一棵树,不过这棵树不是普通的树,而是无向无根树。给我们一个二维数组表示节点之间的连接关系ÿ…...

Python与数据分析--每天绘制Matplotlib库实例图片3张-第1天
目录 1.实例1--Bar color demo 2.实例2--Bar Label Demo 3.实例3--Grouped bar chart with labels 1.实例1--Bar color demo import matplotlib.pyplot as plt # 支持中文 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus…...

pycharm 中package, directory, sources root, resources root的区别
【遇到的问题】 导入yolov5中有utils文件,自己的代码中也有utils文件,使得yolov5中的这部分引用出错了。 【解决方案】 单独建立detection文件夹,把检测相关的都放在这里,yolov5是github上拉取的源码,发现yolov5中fr…...

【谢希尔 计算机网络】第2章 物理层
目录 通信基础 基本概念 两个公式lim 奈氏准则 香农定理 奈氏准则 VS 香农定理 编码与调制 编辑 物理层下面的传输媒体 导引型传输媒体 1. 双绞线 2. 同轴电缆 3. 光缆 非导引型传输媒体 无线电微波通信 卫星通信 无线局域网使用的 ISM 频段 信道复用技术 …...
Eclipse工具使用技巧
1、常用快捷键 ctrlshifto 快速导包 CtrlSpace 内容助理 说明:内容助理。提供对方法,变量,参数,javadoc等得提示,应运在多种场合,总之需要提示的时候可先按此快捷键。注:避免输入法的切换设置与此设置冲突 CtrlShiftSpace 变量提示 Ctrl/ 添加/消除//注释 CtrlShift/ 添加…...
python LeetCode 刷题记录 94
题目 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 代码 递归 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.righ…...

滴滴可观测平台 Metrics 指标实时计算如何实现了又准又省?
在滴滴,可观测平台的 Metrics 数据有一些实时计算的需求,承载这些实时计算需求的是一套又一套的 Flink 任务。之所以会有多套 Flink 任务,是因为每个服务按照其业务观测需要不同的指标计算,也就对应了不同数据处理拓扑。我们尽力抽…...

每天几道Java面试题:IO流(第五天)
目录 第五幕 、第一场)街边 友情提醒 背面试题很枯燥,加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 第五幕 、 第一场)街边 【衣衫褴褛老者,保洁阿姨,面试者老王】 衣衫褴褛老…...
js/axios/umi-request 根据后端返回的二进制流下载文件
type ResponseType {data: Blob;headers: {content-disposition?: string;}; }; // 下载 (创建a标签) export const downloadBlob (response: ResponseType) > {const blob response.data; // 获取响应中的 Blob 数据const contentDisposition response.headers[conten…...
软件评测师之流水线
目录 一.概念二.周期三.执行时间的计算 一.概念 程序在执行时多条指令可以层叠并行的技术。 二.周期 取指→分析→执行 指令执行的各个阶段里面,执行时间最长的为流水线的周期。 三.执行时间的计算 n条指令执行的总时间流水线计算公式:单条指令所需…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...

JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...

理想汽车5月交付40856辆,同比增长16.7%
6月1日,理想汽车官方宣布,5月交付新车40856辆,同比增长16.7%。截至2025年5月31日,理想汽车历史累计交付量为1301531辆。 官方表示,理想L系列智能焕新版在5月正式发布,全系产品力有显著的提升,每…...

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题
20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起,为了跨网段推流,千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…...