驱动代码验证

news2025/1/12 10:50:09

要求

代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

int main(int argc,const char * argv[])
{
    int fd;
    int status;
    if ((fd = open("/dev/my_irq_led1", O_RDWR)) == -1)
    {
        printf("打开设备失败\n");
        exit(-1);
    }
    while (1)
    {
        read(fd,&status,sizeof(status));//阻塞读取数据
        printf("Number:%d\n",status);
    }
    close(fd);   
    return 0;
}
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
/*
    my_irq_led1{
        compatible = "test,my_irq_led1";      //用于获取节点
        reg = <0x12345678 0x14>;
        interrupt-parent = <&gpiof>;  //引用父节点
        interrupts = <9 0>; //这个节点引入的中断管脚
        led1=<&gpioe 10 0>;
    };
*/
#define CNAME "my_irq_led1"
int major;
// 向上申请的结构体目录信息
struct class *cls;
// 向上申请的结构体节点信息
struct device *dev;
wait_queue_head_t wq;
unsigned int condition=0;
unsigned int status=0;
struct device_node *node;
struct gpio_desc *desc;
unsigned int irqnum;

//LED中断函数
irqreturn_t irq_led_handle(int irq, void *dev)
{
    //获取LED的状态赋值给status
    status = gpiod_get_value(desc);
    //状态取反
    status = !status;
    //设置LED的状态
    gpiod_set_value(desc,status);
    //表示当前数据准备好
    condition=1;
    //唤醒休眠进程
    wake_up_interruptible(&wq);
    return IRQ_HANDLED;
}
//打开LED
int irq_led_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
//读数据
ssize_t irq_led_read(struct file *file,char __user *ubuf, size_t size, loff_t *offs)
{
    int ret;
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    if(file->f_flags & O_NONBLOCK){
        //非阻塞
        return -EINVAL;
    }else{
        //阻塞
        ret = wait_event_interruptible(wq,condition);
        if(ret < 0){
            printk("接收信号失败\n");
            return ret;
        }
    }
    //将数据拷贝到用户空间
    if(size > sizeof(status)) size = sizeof(status);
    ret = copy_to_user(ubuf,(void *)&status,size);
    if(ret){
        printk("数据拷贝失败\n");
        return -EIO;
    }
    printk("数据拷贝成功\n");
    //4.将条件清零
    condition = 0;
    return size;
}

//关闭
int irq_led_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
struct file_operations fops = {
    .open = irq_led_open,
    .read = irq_led_read,
    .release = irq_led_close,
};
int pdrv_probe(struct platform_device *pdev)
{
    int ret;
    //1.注册字符设备驱动
    major = register_chrdev(0,CNAME,&fops);
    if(major < 0){
        printk("注册字符设备失败\n");
        ret = major;
        goto ERR1;
    }
    printk("注册字符设备成功\n");
    //2.创建设备节点
    // 向上提交目录信息
    cls = class_create(THIS_MODULE,CNAME);
    if(IS_ERR(cls)){
        printk("向上提交设备目录信息失败\n");
        ret = PTR_ERR(cls);
        goto ERR2;
    }
    printk("向上提交设备目录信息成功\n");

    // 向上提交设备信息
    dev = device_create(cls,NULL,MKDEV(major,0),NULL,CNAME);
    if(IS_ERR(dev)){
        printk("向上提交设备信息失败\n");
        ret = PTR_ERR(dev);
        goto ERR3;
    }
    printk("向上提交设备信息成功\n");
    //3.初始化等待队列头
    init_waitqueue_head(&wq);
    //4.解析设备树节点,申请使用的中断和led
    node = of_find_node_by_path("/irq_led");
    if(node == NULL){
        printk("解析设备树失败");
        ret = -EAGAIN;
        goto ERR4;
    }
    printk("解析设备树成功");
    //获取GPIO结构体信息
    desc = gpiod_get_from_of_node(node,"led1",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(desc)){
        printk("获取GPIO失败\n");
        ret = PTR_ERR(desc);
        goto ERR4;
    }
    //获取软中断号
    irqnum = irq_of_parse_and_map(node,0);
    if(irqnum == 0){
        printk("获取中断号失败\n");
        ret = -EAGAIN;
        goto ERR5;
    }
    printk("获取中断号成功\n");
    //注册中断
    ret = request_irq(irqnum,irq_led_handle,IRQF_TRIGGER_FALLING,CNAME,NULL);
    if(ret){
        printk("注册中断号失败\n");
        goto ERR5;
    }
    printk("注册中断号成功\n");

    return 0;
ERR5:
    gpiod_put(desc);
ERR4:
    device_destroy(cls,MKDEV(major,0));
ERR3:
    class_destroy(cls);
ERR2:
    unregister_chrdev(major,CNAME);
ERR1:
    return ret;
}

//remove设备和驱动分离时执行
int pdrv_remove(struct platform_device *pdev)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    free_irq(irqnum,NULL);
    device_destroy(cls,MKDEV(major,0));
    class_destroy(cls);
    unregister_chrdev(major,CNAME);
    //释放GPIO信息
    gpiod_put(desc);
    return 0;
}

struct of_device_id oftable[] = {
    {.compatible = "test,my_irq_led1"},
    {},
};

struct platform_driver pdrv = {
    .probe = pdrv_probe,
    .remove = pdrv_remove,
    .driver = {
        .name = "ONE",
        .of_match_table = oftable,
    },
};
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

串口显示

实验现象

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移动端h5项目的兼容和适配问题

解决兼容性问题的关键在于对移动端产品的生存环境进行梳理&#xff0c;在此基础之上制定应对策略。 所谓生存环境主要分为三个维度&#xff1a; 硬件环境&#xff0c;细分为品牌和机型&#xff0c;决定了屏幕大小、性能等硬件限制 操作系统&#xff0c;比如iOS6和iOS7&#xf…

Redis数据类型(list\set\zset)

"maybe its why" List类型 列表类型是⽤来存储多个有序的字符串&#xff0c;列表中的每个字符串称为元素&#xff08;element&#xff09;&#xff0c;⼀个列表最多可以存储个2^32 - 1个元素。在Redis中&#xff0c;可以对列表两端插⼊&#xff08;push&#xff09…

555定时器

一、定义 定时器是一种多用途的数字-模拟混合集成电路&#xff0c;可极方便的构成施密特触发器、单稳态触发器和多谐振荡器&#xff0c;其简化原理图及引脚定义如下所示 3个绿色电阻&#xff0c;电阻值为5K&#xff1b;2个黄色和粉色比较器&#xff1b;1个紫色SR触发器&#x…

WPF实战项目十三(API篇):备忘录功能api接口、优化待办事项api接口

1、新建MenoDto.cs /// <summary>/// 备忘录传输实体/// </summary>public class MenoDto : BaseDto{private string title;/// <summary>/// 标题/// </summary>public string Title{get { return title; }set { title value; }}private string con…

实验三十一、OCL 电路输出功率和效率的研究

一、题目 研究 OCL 功率放大电路的输出功率和效率。 二、仿真电路 OCL 功率放大电路如图1所示。 图 1 OCL 功率放大电路 图1\,\,\,\textrm{OCL}\,功率放大电路 图1OCL功率放大电路图中采用 NPN 型低频功率晶体管 2SC2001&#xff0c;其参数为&#xff1a; I C M 700 mA I_…

5G NR:RACH流程 -- Msg1之选择正确的PRACH时频资源

PRACH的时域资源是如何确定的 PRACH的时域资源主要由参数“prach-ConfigurationIndex”决定。拿着这个参数的取值去协议38211查表6.3.3.2-2/3/4&#xff0c;需要注意根据实际情况在这三张表中进行选择&#xff1a; FR1 FDD/SULFR1 TDDFR2 TDD Random access preambles can onl…

信号和槽的相关操作

目录 信号和槽 connect()函数 自定义信号槽 例子 自定义信号槽需要注意的事项 信号槽的更多用法 Lambda表达式 ① 函数对象参数 ② 操作符重载函数参数 ③ 可修改标示符 ④ 错误抛出标示符 ⑤ 函数返回值 ⑥ 是函数体 所谓信号槽&#xff0c;实际就是观察者模式。当…

AVS3变换:PBT、ST和SBT

前面的文章介绍了AVS3中的变换工具IST和ISTS&#xff0c;本文将介绍AVS3中剩余的几种变换工具&#xff1a;基于位置的变换&#xff08;PBT,Position Based Transform&#xff09;、二次变换&#xff08;ST, Secondary Transform&#xff09;和子块变换&#xff08;SBT, Sub-Blo…

SmartInspect Professional .Net Delphi Crack

SmartInspect Professional .Net & Delphi Crack SmartInspect Professional是一个用于调试和跟踪.NET、Java和Delphi软件的高级日志记录工具。它使您能够识别错误&#xff0c;找到客户问题的解决方案&#xff0c;并让您清楚地了解软件在不同环境和条件下的工作方式。可以轻…

给oracle逻辑导出clob大字段、大数据量表提提速

文章目录 前言一、大表数据附&#xff1a;查询大表 二、解题思路1.导出排除大表的数据2.rowid切片导出大表数据Linux代码如下&#xff08;示例&#xff09;&#xff1a;Windows代码如下&#xff08;示例&#xff09;&#xff1a;手工执行代码如下&#xff08;示例&#xff09;&…

java八股文面试[多线程]——Synchronized的底层实现原理

笔试&#xff1a;画出Synchronized 线程状态流转实现原理图 synchronized关键字解决的是多个线程之间访问资源的同步性&#xff0c;synchronized 翻译为中文的意思是同步&#xff0c;也称之为”同步锁“。 synchronized的作用是保证在同一时刻&#xff0c; 被修饰的代码块或方…

任意文件上传

文章目录 渗透测试漏洞原理任意文件上传1. 任意文件上传概述1.1 漏洞成因1.2 漏洞原理1.3 漏洞危害1.4 漏洞的利用方法1.5 漏洞的验证 2. WebShell解析2.1 Shell2.1.1 命令解释器 2.2 WebShell2.2.1 大马2.2.2 小马2.2.3 GetShell2.2.4 WebShell项目 3. 任意文件上传攻防3.1 毫…

注册字符设备

五、注册字符设备 struct cdev {struct kobject kobj;//表示该类型实体是一种内核对象struct module *owner;//填THIS_MODULE&#xff0c;表示该字符设备从属于哪个内核模块const struct file_operations *ops;//指向空间存放着针对该设备的各种操作函数地址struct list_head …

RAD Installer Crack,集成到RAD Studio IDE支持

RAD & Installer Crack,集成到RAD Studio IDE支持 用于创建NSIS和Inno Setup安装程序的RAD Studio扩展。它将NSIS(Nullsoft Scriptable Install System)和Inno Setup与Embarcadero RAD Studio IDE结合在一起。它允许您在RAD Studio中设计和构建NSIS和Inno Setup项目&#x…

错误的迷宫:探索开发中的异常管理之旅

引言&#xff1a;为什么我们需要谈论错误处理&#xff1f; 在软件开发的世界中&#xff0c;错误是不可避免的。它们是我们编程旅程中的挑战&#xff0c;但也是我们成长的机会。正确地处理错误不仅可以确保软件的稳定性和可靠性&#xff0c;还可以为开发者提供宝贵的反馈。本文…

Icon设计神器!这5个软件一定要试试

在界面设计中&#xff0c;Icon既可以为用户指明用途&#xff0c;又可以提升界面设计的质感&#xff0c;可以说是一种必不可少的设计素材。而市面上可以制作的Icon的设计软件也十分丰富&#xff0c;今天本文将选出了5个好用的与大家分享&#xff0c;它们不仅功能强大&#xff0c…

RunnerGo:高效、易用的性能测试神器

你是否曾经遇到过这样的难题&#xff1a;在测试软件性能时&#xff0c;缺乏高效且易用的测试工具&#xff0c;导致测试过程繁琐&#xff0c;测试用例难以管理&#xff0c;测试报告也不尽人意。这些问题让我们在测试过程中倍感困扰。然而&#xff0c;现在有了RunnerGo这款性能测…

基于SpringBoot高校心理教育辅导设计与实现【附开题|万字文档(LW)和搭建文档】

主要功能 前台界面&#xff1a; ①首页、公告管理、查看更多等 ②心理健康学习、文章标题搜索、试卷列表、考试等 ③公告通知、留言反馈等 ④个人中心、考试记录、错题本等 后台登录&#xff1a; ①学生登录&#xff1a; 个人中心、修改密码、个人信息、辅导预约管理、考试管理…

(详解)数据结构-----------栈与队列 c语言实现

本章将会详细讲解以下知识点&#xff1a; 目录 一&#xff1a;栈 1&#xff1a;栈的定义&#xff0c;栈的特点 2&#xff1a;用什么结构来实现栈与原因的分析? 3: (超详解)栈的常用接口并且附上测试用例 二:队列 1:队列的定义&#xff0c;队列的特点 2&#xff1a;用什么结…

QT6为工程添加资源文件

如果在同一个文件夹 如果不在同一个文件夹 然后浏览资源位置&#xff0c;找到文件就可以了