1.内核驱动中,驱动注册,阻塞IO,gpio子系统,中断处理的整体结合示例

news2024/12/28 5:01:35

一,功能实现要求

/*功能实现 在stm32开发板上实现功能

           1.使用阻塞IO读取number变量的值,当number的值改变时打印number的值

           2.注册KEY1按键的驱动和LED1的驱动以及对应的设备文件,

           3.按键和指示灯设备信息放在同一个设备树的节点中

           4.当KEY1按下时LED1灯的状态取反,number的值取反,number值为0或1

           */

二,示例图

 三,驱动注册(无实际功能)

        1.主要实现手动注册驱动,并自动提交目录以及myled1和mykey1两个设备文件

int request_dev(void)
{
    int i;
    // 1.实例化字符设备驱动对象
    cdev = cdev_alloc();
    if (cdev == NULL)
    {
        ret = -ENOMEM;
        goto OUT1;
    }
    // 2.部分初始化字符设备驱动对象
    cdev_init(cdev, &fops);
    // 3.申请设备号
    if (my_major == 0) // 动态申请设备号
    {
        ret = alloc_chrdev_region(&devno, my_minor, 3, "mycdev"); // 成功返回0,失败返回错误码
        if (ret)
        {
            printk("动态申请设备号失败\n");
            goto OUT2;
        }
        printk("动态申请设备号成功\n");
        my_major = MAJOR(devno); // 获取主设备号
        my_minor = MINOR(devno); // 获取次设备号
    }
    else // 静态制定设备号
    {
        // 通过自定义主设备号和次设备号获取设备号
        devno = MKDEV(my_major, 0);
        ret = register_chrdev_region(devno, 3, "mycdev"); // 成功申请设备号返回0,失败返回错误码
        if (ret)
        {
            printk("静态申请设备号失败\n");
            goto OUT2;
        }
        printk("静态申请设备号成功\n");
    }
    // 4.将字符设备驱动对象注册进内核
    ret = cdev_add(cdev, devno, 3);
    if (ret)
    {
        printk("字符设备驱动注册进内核失败\n");
        goto OUT3;
    }
    printk("字符设备驱动注册进内核成功\n");
    // 5.自动创建设备节点
    // 向上提交目录
    cls = class_create(THIS_MODULE, "mycdev");
    if (IS_ERR(cls)) // 为真表示cls指向4K的预留空间
    {
        printk("向上提交目录失败\n");
        ret = -PTR_ERR(cls);
        goto OUT4;
    }
    printk("向上提交目录成功\n");
    // 自动创建设备文件LED1
    dev = device_create(cls, NULL, MKDEV(my_major, 0), NULL, "myled1");
    if (IS_ERR(dev))
    {
        printk("自动创建设备文件myled1失败\n");
        ret = PTR_ERR(dev);
        goto OUT5;
    }
    printk("自动创建设备文件myled1成功\n");

    // 自动创建设备文件KEY1
    dev = device_create(cls, NULL, MKDEV(my_major, 1), NULL, "mykey1");
    if (IS_ERR(dev))
    {
        printk("自动创建设备文件mykey1失败\n");
        ret = PTR_ERR(dev);
        goto OUT5;
    }
    printk("自动创建设备文件mykey1成功\n");
    return 0;
OUT5:
    // 释放提交成功的设备节点信息
    for (--i; i >= 0; i--)
    {
        device_destroy(cls, MKDEV(my_major, i));
    }
    // 销毁目录
    class_destroy(cls);
OUT4:
    cdev_del(cdev);
OUT3:
    unregister_chrdev_region(devno, 3);
OUT2:
    kfree(cdev);
OUT1:
    return ret;
}

 四,LED1灯的初始化

        采用从自定义的设备树节点中获取LED1的GPIO对象信息,为LED1灯各个寄存器使能。只需手动调用电平改变函数gpiod-set-value即可实现灯的亮灭.

int request_LED(void)
{
    // 1.解析设备树节点信息通过名字
    dnode = of_find_node_by_name(NULL, "numbers");
    if (dnode == NULL)
    {
        printk("设备树节点解析失败\n");
        return -ENOMEM;
    }
    printk("设备树节点解析成功\n");

    // 2.通过节点信息获取GPIO对象
    // 2.1申请LED1对应资源
    gpiono_led1 = gpiod_get_from_of_node(dnode, "led1", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(gpiono_led1))
    {
        printk("LED1资源申请失败\n");
        return -PTR_ERR(gpiono_led1);
    }
    printk("LED1资源申请成功\n");
    return 0;
}

5.按键中断的初始化

        也是根据自己定义的设备树节点中获取信息,申请对应的软中断号,然后根据获取到的软终断号初始化中断号,从而实现中断发生回调中断处理函数处理中断时间。

int request_interrupts(void)
{
    // 准备:在设备树中添加gpiof组控制按键的节点信息
    // 1.在设备数中寻找到对应设备树节点的信息 of_find_node_by_name
    dnode = of_find_node_by_name(NULL, "numbers");
    if (dnode == NULL)
    {
        printk("节点信息获取失败\n");
        return -ENXIO;
    }
    printk("节点信息获取成功\n");
    // 2.根据节点地址寻找key对应的软中断号 irq_of_parse_and_map
    // 获取KEY按键对应的软中断号 参2的索引的值在于你的自定义节点GPIO控制所在位置,
    // myirq{
    //     interrupts-extended=<&gpiof 9 0>,<&gpiof 7 0>,<&gpiof8 0>;
    // };KEDY1对应<&gpiof 9 0>索引为0,KEY2对应<&gpiof 7 0>,索引为1,类似数组依次对应

    myirq_key[0] = irq_of_parse_and_map(dnode, 0);
    if (!myirq_key[0])
    {
        printk("key1软中断号获取失败\n");
        return ENOMEM;
    }
    printk("key1软中断号获取成功\n");

    // 3.注册中断号 包括对应的软中断号,中断执行的处理函数,中断的检测方式,中断名
    // 注册KEY对应的软中断号
    // 参1:中断号对应的软中断号 参2:中断的处理函数 参3:中断触发的方式 参4:为中断起一个名字 参5:给中断函数传递的值

    // KEY1
    ret = request_irq(myirq_key[0], myirq_handler, IRQF_TRIGGER_FALLING, irq_key1_name, 0);
    if (ret < 0)
    {
        printk("key1中断注册失败\n");
        return ret;
    }
    printk("key1中断注册成功\n");
    return 0;
}

6.阻塞IO

        当中断没有发生时,函数一直处于等待状态,当中断发生,标志位的值改变,从而使函数往下运行,改变number内核变量的值

int my_wait(void)
{
    // 判断condition的值,为1则改变number的值
    wait_event_interruptible(wq_head, condition);
    if (number==1)
    {
        number = 0;
    }
    else if(number==0)
    {
        number = 1;
    }
    condition = 0;
    return 0;
}

7.按键中断处理函数

        根据LED1现在的状态改变,更改标志位并唤醒睡眠中的进程。实现功能的要求。

// 中断处理函数
irqreturn_t myirq_handler(int irqno, void *dev_id)
{
    printk("软中断号%d的处理\n", irqno);
    // 改变LED灯的状态
    gpiod_set_value(gpiono_led1, !gpiod_get_value(gpiono_led1));
    // 改变number的值
    //  改变标志
    condition = 1;
    // 唤醒可中断进程
    wake_up_interruptible(&wq_head);
    return IRQ_HANDLED;
}

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

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

相关文章

TypeScript 类型体操:合并映射类型的处理结果为联合类型(记录)

一般索引索引 type boy {name : string,age : number } 对索引类型映射 type onlyBoy<obj> {readonly [key in keyof obj] : obj[key] } 使用 type res onlyBoy<boy>; 输出 这些都是对索引类型整体做的变换&#xff0c;变换的结果依然是一个索引类型。有的…

提示“无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动”,如何解决?

在aspx网站部署过程中&#xff0c;出现“无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动”的提示&#xff0c;如下图&#xff0c;如何解决&#xff1f; 解决方案1&#xff1a; Web.Config里面 把sessionState 的mode改为&quo…

ChatGPT对高校人才培养模式的挑战与应对策略思考

酷吗&#xff1f;输入指令后直接就能生成一大串代码&#xff0c;即使不懂相关技术也能玩转编程&#xff0c;这就是ChatGPT赋予你的“新能力”&#xff0c;除了写代码&#xff0c;ChatGPT还能帮你执行各种五花八门的任务。 AI工具如ChatGPT在行业中的广泛应用对于行业的人才结…

全网最牛,Python自动化测试-日志Log处理(超细)一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 日志就是用于记录…

如何安装本地Go Tour教程(或者叫A Tour of Go离线版),以及中文版安装不了该怎么办

Go 官方是有一个在线教程 A Tour of Go&#xff0c;可以在线学习 Go 的编程&#xff0c;并且有中文版。英文原版页面如下&#xff1a; 出人意料的是&#xff0c;Go 提供了离线版&#xff08;各个语言都有&#xff09;&#xff0c;下载安装之后就可以在本地编译运行查看结果&a…

python subprocess.run() subprocess.Popen()(执行系统命令、启动新的进程、连接到子进程的输入/输出管道)

文章目录 python subprocess基本函数subprocess.runsubprocess.Popensubprocess.Popen参数解释- args&#xff1a;要执行的命令及其参数。可以是一个字符串或一个字符串列表。- bufsize&#xff1a;指定缓冲区的大小。默认值为-1&#xff0c;表示使用系统默认的缓冲区大小。- e…

Redis基本全局命令(含key过期策略)

Redis基本全局命令 KEYEXISTSDELEXPIRETTLRedis的key过期策略TYPE KEY 返回所有满⾜样式&#xff08;pattern&#xff09;的key。⽀持如下统配样式。 h?llo 匹配 hello , hallo 和 hxlloh*llo 匹配 hllo 和 heeeelloh[ae]llo 匹配 hello 和 hallo 但不匹配 hilloh[^e]llo 匹配…

opencv-图像处理基础-二值图像

opencv学习01_图像处理基础_二值图像 1&#xff0e;二值图像 二值图像是指仅仅包含黑色和白色两种颜色的图像。 在计算机中&#xff0c;通过一个栅格状排列的数据集&#xff08;矩阵&#xff09;来表示和处理图像。例如&#xff0c;图 2-1 是 一个字母 A 的图像&#xff0c;计算…

【优选算法题练习】day4

文章目录 一、3. 无重复字符的最长子串1.题目简介2.解题思路3.代码4.运行结果 二、1004. 最大连续1的个数 III1.题目简介2.解题思路3.代码4.运行结果 三、1658. 将 x 减到 0 的最小操作数1.题目简介2.解题思路3.代码4.运行结果 总结 一、3. 无重复字符的最长子串 1.题目简介 …

Java设计模式之结构型-代理模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 1、静态代理类图 2、动态代理类图 三、角色设计 四、案例分析 1、静态代理 2、JDK动态代理 3、Cglib动态代理 五、总结 一、基础概念 代理模式是一种结构型设计模式&#xff0c;它用一个代理对象来封装一个目标对象&#xff0c;通常…

Java的运算符

运算符介绍 运算符是一种特殊的符号&#xff0c;用以表示数据的运算、赋值和比较等。 运算符介绍 算术运算符赋值运算符关系运算符 [比较运算符]逻辑运算符位运算符 [需要二进制基础]三元运算符 算术运算符 介绍 算术运算符是对数值类型的变量进行运算的&#xff0c;在 Ja…

学习记录——Transformer、ViT、Swin-Transformer、SegFormer、TopFormer、Seaformer

Transformer 2017 Computation and Language Google Self-Attention、Multi-Head Attention 位置编码 原理参考链接 ransformer网络结构&#xff1a; ViT 2020 ICLR 将transformer引入到cv领域 将输入图片224x224x3按照16x16x3大小的Patch进行划分&#xff0c;接着通过…

JAVA+Selenium最简单的处理登录弹窗的方式

在做自动化测试遇到需要处理登录弹窗情况&#xff0c;例如我的用户名为admin, 密码为admin, 那么想要登录http://10.10.168.1, 只需要使用以下链接访问即可立即登录, 并免除弹窗: http://账号:密码网址

sys V 进程间通信之共享内存

note 1.使用shmget将在内核创建一个共享内存区 2.使用shmctl才可以删除内核创建的共享内存区 3.使用shmat给当前进程开辟与内核共享内存对应的内存区p&#xff0c;用户态对p的操作会作用到内核共享内存区 code #include <stdio.h> #include <stdlib.h> #inclu…

ROS:Rviz中控制机器人模型运动

目录 一、Arbotix简介二、安装 Arbotix二、Arbotix使用案例2.1需求2.2流程2.2.1创建新功能包&#xff0c;准备机器人 urdf、xacro 文件2.2.2添加 Arbotix 配置文件2.2.3编写 launch 文件配置 Arbotix2.2.4启动 launch 文件并控制机器人模型运动 一、Arbotix简介 Arbotix 是一款…

Python 标签(便签贴)打印,直接连接打印机打印

前言&#xff1a;一开始试了好多打印方式&#xff0c;图片打印很糊&#xff0c;docx文件打印效果最好&#xff0c;但是每次打印会打开Word 影响效率&#xff0c;PDF也会打开PDF软件&#xff0c;打印效果略差于docx文件&#xff0c;TXT文件又不能设置字体&#xff0c;找了好久&a…

8 Surprising Things You Can Do With ChatGPT 你可以用 ChatGPT 做的 8 件令人惊讶的事情

If you’ve heard about ChatGPT and think it’s just a fancy chatbot, you might be underestimating the range of what it can do. Here are some surprising things you can do with ChatGPT, whether you want to write a resume or have it dungeon-master an epic rol…

第二章(二):Django框架Model之ORM操作数据库:增、删、改、查

系列文章目录 备注&#xff1a;这里是Django系列文章的所有文章的目录 第一章(一) : Django框架之创建项目/应用/templates、连接MYSQL、配置日志LOGGING、启动django项目 第一章(二)&#xff1a;Django框架的模式、路由、视图&#xff1b; 第一章(三)&#xff1a;Django框架的…

Linux14.文件(下)

文件描述符fd&#xff0c;分配到的是从0开始最小的没有被占用的。 2.输出重定向(重定向的本质&#xff0c;就是在操作系统内部更改fd对应的内容的指向)&#xff0c;同时理解输入重定向和追加重定向。 3.重定向函数dup2(oldfd, newfd)&#xff0c;oldfd -> newfd (小技巧:一…

jennkins配置k8s动态slave

一、 首先完成jenkins的部署可参考jenkins部署 二、 如果是在同一个k8s集群下部署的则直接这样配置 在security中agent的端口也配置成50000 如果是虚拟机中部署的jenkins添加k8s需要做如下操作 echo ‘certificate-authority-data-value’ | base64 -d > ./ca.crt &#…