驱动day10

news2024/11/18 23:02:33

练习

基于platform实现
在这里插入图片描述

设备树

 myplatform_homework{
        compatible = "hqyj,myplatform_homework";      //用于获取节点
                reg = <0x12345678 14>;
        interrupt-parent = <&gpiof>;  //引用父节点
        interrupts = <9 0>; //这个节点引入的中断管脚
        led1-gpio = <&gpioe 10 0>;
    };

应用程序

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char const *agrv[])
{
    unsigned int number = 0;
    int fd = open("/dev/myplatform", O_RDWR);
    if (fd < 0)
    {
        printf("打开设备文件失败\n");
        return -1;
    }
    printf("打开设备文件成功\n");

    while (1)
    {
        read(fd, &number, sizeof(number));
        printf("number = %d\n", number);
    }
    close(fd);
    return 0;
}

驱动

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/interrupt.h>

struct resource *res;
unsigned int irqno;
struct gpio_desc *gpiono;
unsigned int condition = 0;
unsigned int status = 0;
// 定义等待队列头
wait_queue_head_t wq_head;
unsigned int major = 0;
struct class *cls;
struct device *dev;

// 定义中断处理函数
irqreturn_t key_handler(int irq, void *dev)
{
    status = gpiod_get_value(gpiono);
    status = !status;
    gpiod_set_value(gpiono, status);

    condition = 1;
    wake_up_interruptible(&wq_head); // 唤醒休眠的进程

    return IRQ_HANDLED;
}

// 封装操作方法
ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{
    if (size > sizeof(status))
        size = sizeof(status);
    wait_event_interruptible(wq_head, condition);
    int ret = copy_to_user(ubuf, (void *)&status, size);
    if (ret)
    {
        printk("copy_to_user failed\n");
        return ret;
    }
    condition = 0; // 表示下次的数据没有准备好

    return 0;
}
// 定义一个操作方法结构体变量并且初始化
struct file_operations fops = {
    .read = mycdev_read,
};

// 1.封装probe函数和remove函数
int pdrv_probe(struct platform_device *pdev) // 在进入probe函数的时候节点已经被放在pdev->dev.of_node中了
{
    int ret;
    // 1.注册字符设备驱动
    major = register_chrdev(0, "myplatform", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        ret = major;
        goto ERR1;
    }
    printk("注册字符设备驱动成功major=%d\n", major);

    // 2.创建设备节点
    cls = class_create(THIS_MODULE, "myplatform");
    if (IS_ERR(cls))
    {
        printk("向上提交目录信息失败\n");
        ret = PTR_ERR(cls);
        goto ERR2;
    }
    printk("向上提交目录信息成功\n");

    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "myplatform");
    if (IS_ERR(dev))
    {
        printk("向上提交设备节点失败\n");
        ret = PTR_ERR(dev);
        goto ERR3;
    }
    printk("向上提交设备节点成功\n");

    // 3.初始化等待队列头
    init_waitqueue_head(&wq_head);

    gpiono = gpiod_get_from_of_node(pdev->dev.of_node, "led1-gpio", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(gpiono))
    {
        printk("解析gpio信息失败\n");
        ret = PTR_ERR(gpiono);
        goto ERR4;
    }
    printk("解析gpio信息成功\n");

    irqno = platform_get_irq(pdev, 0); // 获取中断的信息
    if (irqno < 0)
    {
        printk("获取中断类型资源失败\n");
        ret = irqno;
        goto ERR5;
    }
    printk("软中断号: %d\n", irqno);

    ret = request_irq(irqno, key_handler, IRQF_TRIGGER_FALLING, "myplatform", NULL);
    if (ret)
    {
        printk("注册中断失败\n");
        goto ERR5;
    }
    printk("注册中断成功\n");

    return 0;
ERR5:
    gpiod_put(gpiono);
ERR4:
    device_destroy(cls, MKDEV(major, 0));
ERR3:
    class_destroy(cls);
ERR2:
    unregister_chrdev(major, "myplatform");
ERR1:
    return ret;
}
int pdrv_remove(struct platform_device *pdev)
{
    // 关灯
    gpiod_set_value(gpiono, 0);
    // 释放gpio信息
    gpiod_put(gpiono);
    unregister_chrdev(major, "myplatform");
    class_destroy(cls);
    device_destroy(cls, MKDEV(major, 0));
    free_irq(irqno, NULL);

    return 0;
}

struct of_device_id oftable[] = {
    {.compatible = "hqyj,myplatform_homework"},
    {.compatible = "hqyj,myplatform_homework1"},
    {.compatible = "hqyj,myplatform_homework2"},
    {}, // 防止数组越界
};

// 2.分配驱动信息对象并初始化
struct platform_driver pdrv = {
    .probe = pdrv_probe,
    .remove = pdrv_remove,
    .driver = {
        .name = "aaaaa",           // 用于名字匹配
        .of_match_table = oftable, // 用于设备树匹配
    },
};

// 一键注册宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");```

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

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

相关文章

Git 简单介绍

Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。 一、Git 安装 windows安装&#xff1a;进入网站 https://git-scm.com/ 安装&#xff0c;ubuntu配置&#xff1a;apt install git。当前于 Win 下已安装 Git 版本 2.40.1。 二、配置 设…

ModStartBlog v8.1.0 博客密码访问,内容编辑升级

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议。 功能特性 丰富的模块市场&#xff0c;后台一键快速安装 …

LLMs之Code:SQLCoder的简介、安装、使用方法之详细攻略

LLMs之Code&#xff1a;SQLCoder的简介、安装、使用方法之详细攻略 目录 SQLCoder的简介 1、结果 2、按问题类别的结果 SQLCoder的安装 1、硬件要求 2、下载模型权重 3、使用SQLCoder 4、Colab中运行SQLCoder 第一步&#xff0c;配置环境 第二步&#xff0c;测试 第…

Jetson Xavier NX安装torch环境

设备简介 Jetson Xavier NX是一款具有强大计算能力的AI处理器&#xff0c;它采用了NVIDIA的Turing架构和Volta GPU架构&#xff0c;可以实现高性能的深度学习和推理任务。具体性能如下&#xff1a; CPU&#xff1a;6核心ARM Cortex-A57处理器&#xff0c;最高主频1.5GHz。 GP…

一文讲透 JavaScript 应用的演进历程

在不断发展的软件开发领域中&#xff0c;很少有编程语言像JavaScript一样产生深远的影响。它起初只是一种简单的脚本语言&#xff0c;但如今已成为现代Web的驱动力量&#xff0c;改变了应用构建和体验的方式。本文将带你沿着时间线&#xff0c;穿越JavaScript的演进历程&#x…

【网络BSP开发经验】Linux gmac驱动调试(FH8626)

文章目录 Linux网络设备驱动简介Linux网卡驱动网络协议接口层网络设备接口层设备驱动功能层网络设备与媒介层linux驱动数据结构linux驱动注册过程网络设备驱动的注册与注销linux驱动数据包收发流程 Linux PHY驱动MDIO接口PHY简介PHY关联过程PHY状态机对端MAC情况&#xff08;接…

便携式水质检测仪都测哪些水中指标

水质检测仪分为实验室&#xff08;台式&#xff09;和户外使用的便携式多参数水质检测仪。 便携式的有哪些特点&#xff1f; 相对于实验室的水质分析设备&#xff0c;便携式水质多参数分析仪体积小巧&#xff0c;结构简单&#xff0c;户外使用更加便捷&#xff0c;功能更丰富。…

OLED透明屏暗斑问题解析:原因、解决方案与行业趋势

OLED透明屏作为一项创新技术&#xff0c;广泛应用于广告、零售和汽车等领域&#xff0c;其高透明度和出色的显示效果备受青睐。 然而&#xff0c;一些用户反映在使用过程中出现了暗斑问题&#xff0c;影响了显示效果。 那么&#xff0c;在这篇文章中&#xff0c;尼伽将和大家…

RT_Thread内核机制学习(六)互斥量

互斥量 互斥量是特殊的信号量&#xff0c;资源个数只能是0、1&#xff0c;实现了优先级继承。 互斥量优点&#xff1a;谁拥有谁释放&#xff0c;优先级继承。 信号量的缺点&#xff1a;谁都可以释放信号量、优先级反转。 HP被MP抢占&#xff0c;优先级反转。 互斥量实现了优…

MySQL备份和还原

前言 mysql日志默认保存在/usr/local/mysql/data 常见的日志&#xff1a; 1、错误日志 2、一般查询日志 3、二进制日志 4、中继日志 5、重做日志 6、回滚日志 7、慢查询日志 配置文件位置 vim /etc/my.cnf 错误日志&#xff0c;用来记录当MySQL启动、停止或运行时发生的错误信…

Java 数据结构使用学习

Set和List的区别 Set 接口实例存储的是无序的&#xff0c;不重复的数据。List 接口实例存储的是有序的&#xff0c;可以重复的元素。 Set 检索效率低下&#xff0c;删除和插入效率高&#xff0c;插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。 List 和数…

Linux-crontab使用问题解决

添加定时进程 终端输入&#xff1a; crontab -e选择文本编辑方式&#xff0c;写入要运行的脚本&#xff0c;以及时间要求。 注意&#xff0c;如果有多个运行指令分两种情况&#xff1a; 1.多个运行指令之间没有耦合关系&#xff0c;分别独立&#xff0c;则可以直接分为两个…

C++学习记录——이십구 异常

文章目录 1、异常概念2、实际用法3、C标准库的异常体系4、重新抛出异常5、优缺点 1、异常概念 C语言处理错误有assert&#xff0c;返回错误码来处理错误的方式&#xff0c;不过release模式下assert无效&#xff0c;错误码需要程序员自己去查看是什么错误。 C认为应当能给到程…

LLMs之Code:Code Llama的简介、安装、使用方法之详细攻略

LLMs之Code&#xff1a;Code Llama的简介、安装、使用方法之详细攻略 导读&#xff1a;2023年08月25日(北京时间)&#xff0c;Meta发布了Code Llama&#xff0c;一个可以使用文本提示生成代码的大型语言模型(LLM)。Code Llama是最先进的公开可用的LLM代码任务&#xff0c;并有潜…

会玩这10个Linux命令,一定是个有趣的IT男!

Linux当中有很多比较有趣的命令&#xff0c;可以动手看看&#xff0c;很简单的。 1、rev命令 一行接一行地颠倒所输入的字符串。 运行&#xff1a; $rev 如输入&#xff1a;shiyanlou shiyanlou 2、asciiview命令 1)先安装aview $sudo apt-get install aview 2)再安装…

第八周第二天学习总结 | MySQL入门及练习学习第四天

实操练习&#xff1a; 1.建立一个员工表和与之对应的部门表 2.建立外键约束 3.使用多表查询&#xff0c;直接查询部门表和员工表 发现&#xff1a;有很多多余的因笛卡尔乘积而带来的多余输出内容 我想要的到简单明了的数据结果&#xff0c;要消除多于因笛卡尔乘积带来的输出…

3d激光slam建图与定位(2)_aloam代码阅读

1.常用的几种loam算法 aloam 纯激光 lego_loam 纯激光 去除了地面 lio_sam imu激光紧耦合 lvi_sam 激光视觉 2.代码思路 2.1.特征点提取scanRegistration.cpp&#xff0c;这个文件的目的是为了根据曲率提取4种特征点和对当前点云进行预处理 输入是雷达点云话题 输出是 4种特征点…

【Apollo学习笔记】——规划模块TASK之PATH_ASSESSMENT_DECIDER

文章目录 前言PATH_ASSESSMENT_DECIDER功能简介PATH_ASSESSMENT_DECIDER相关信息PATH_ASSESSMENT_DECIDER总体流程1. 去除无效路径2. 分析并加入重要信息给speed决策SetPathInfoSetPathPointType 3. 排序选择最优的路径4. 更新必要的信息 前言 在Apollo星火计划学习笔记——Ap…

信息系统项目管理师(第四版)教材精读思维导图-第七章项目立项管理

请参阅我的另一篇文章&#xff0c;综合介绍软考高项&#xff1a; 信息系统项目管理师&#xff08;软考高项&#xff09;备考总结_计算机技术与软件专业技术_铭记北宸的博客-CSDN博客 本章思维导图PDF格式 本章思维导图XMind源文件 ​ 目录 7.1 项目建议与立项申请 7.2 项目可…

【洛谷】P1873 EKO / 砍树

原题链接&#xff1a;https://www.luogu.com.cn/problem/P1873 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 整体思路&#xff1a;二分答案 设置一个变量highest来记录最高的树的高度&#xff0c;sum记录切下的木头的长度。令左边界l0&#xff0c…