当前位置: 首页 > news >正文

嵌入式:驱动开发 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

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

【ComfyUI】安装 之 window版

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

iMazing 2 .17.9最新官方中文版免费下载安装激活

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

Postman应用——Pre-request Script和Test Script脚本介绍

文章目录 Pre-request Script所在位置CollectionFolderRequest Test Script所在位置CollectionFolderRequest Pre-request Script&#xff08;前置脚本&#xff09;&#xff1a;可以使用在Collection、Folder和Request中&#xff0c;并在Request请求之前执行&#xff0c;可用于…...

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创建型&#xff1a;创建对象3.1.1 单例模式定义最佳实践场景…...

外国固定资产管理系统功能有哪些

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

Postman应用——控制台调试

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

如何制作思维导图?

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

【力扣每日一题】2023.9.21 收集树中金币

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一棵树&#xff0c;不过这棵树不是普通的树&#xff0c;而是无向无根树。给我们一个二维数组表示节点之间的连接关系&#xff…...

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文件&#xff0c;自己的代码中也有utils文件&#xff0c;使得yolov5中的这部分引用出错了。 【解决方案】 单独建立detection文件夹&#xff0c;把检测相关的都放在这里&#xff0c;yolov5是github上拉取的源码&#xff0c;发现yolov5中fr…...

【谢希尔 计算机网络】第2章 物理层

目录 通信基础 基本概念 两个公式lim 奈氏准则 香农定理 奈氏准则 VS 香农定理 编码与调制 ​编辑 物理层下面的传输媒体 导引型传输媒体 1. 双绞线 2. 同轴电缆 3. 光缆 非导引型传输媒体 无线电微波通信 卫星通信 无线局域网使用的 ISM 频段 信道复用技术 …...

Eclipse工具使用技巧

1、常用快捷键 ctrlshifto 快速导包 CtrlSpace 内容助理 说明:内容助理。提供对方法,变量,参数,javadoc等得提示,应运在多种场合,总之需要提示的时候可先按此快捷键。注:避免输入法的切换设置与此设置冲突 CtrlShiftSpace 变量提示 Ctrl/ 添加/消除//注释 CtrlShift/ 添加…...

python LeetCode 刷题记录 94

题目 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 代码 递归 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.righ…...

滴滴可观测平台 Metrics 指标实时计算如何实现了又准又省?

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

每天几道Java面试题:IO流(第五天)

目录 第五幕 、第一场&#xff09;街边 友情提醒 背面试题很枯燥&#xff0c;加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 第五幕 、 第一场&#xff09;街边 【衣衫褴褛老者&#xff0c;保洁阿姨&#xff0c;面试者老王】 衣衫褴褛老…...

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…...

软件评测师之流水线

目录 一.概念二.周期三.执行时间的计算 一.概念 程序在执行时多条指令可以层叠并行的技术。 二.周期 取指→分析→执行 指令执行的各个阶段里面&#xff0c;执行时间最长的为流水线的周期。 三.执行时间的计算 n条指令执行的总时间流水线计算公式&#xff1a;单条指令所需…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...