驱动开发DAY 7

news2024/11/15 10:51:43

代码: 

homework.h

#ifndef __HOMEWORK_H__
#define __HOMEWORK_H__

#define LED1_ON  _IO('L',(0x1<<1))
#define LED1_OFF _IO('L',(0x1<<2))
#define LED2_ON  _IO('L',(0x1<<3))
#define LED2_OFF _IO('L',(0x1<<4))
#define LED3_ON  _IO('L',(0x1<<5))
#define LED3_OFF _IO('L',(0x1<<6))

#endif

部分设备树

	myleds{
		led1=<&gpioe 10 0>;
		led2=<&gpiof 10 0>;
		led3=<&gpioe 8 0>;
	};

 homework.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device/class.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
#include "homework.h"
#define COUNT (3)                       // 设备文件数目
struct gpio_desc *gpionum[COUNT];       // gpio结构体
int myopen(struct inode *inode, struct file *file){printk("%s.\n", __func__);return 0;}
int myclose(struct inode *inode, struct file *file){printk("%s.\n", __func__);return 0;}
long myioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    printk("%s.\n", __func__);
    switch(MINOR(file->f_inode->i_rdev))
    {
        case 0:
            switch(cmd)
            {
                case LED1_ON:
                    printk("LED1_ON.\n");
                    gpiod_set_value(gpionum[0], 1);
                    break;
                case LED1_OFF:
                    printk("LED1_OFF.\n");
                    gpiod_set_value(gpionum[0], 0);
                    break;
                default:
                    printk("传入cmd错误.\n");
                    break;
            }
            break;
        case 1:
            switch(cmd)
            {
                case LED2_ON:
                    printk("LED2_ON.\n");
                    gpiod_set_value(gpionum[1], 1);
                    break;
                case LED2_OFF:
                    printk("LED2_OFF.\n");
                    gpiod_set_value(gpionum[1], 0);
                    break;
                default:
                    printk("传入cmd错误.\n");
                    break;
            }
            break;
        case 2:
            switch(cmd)
            {
                case LED3_ON:
                    printk("LED3_ON.\n");
                    gpiod_set_value(gpionum[2], 1);
                    break;
                case LED3_OFF:
                    printk("LED3_OFF.\n");
                    gpiod_set_value(gpionum[2], 0);
                    break;
                default:
                    printk("传入cmd错误.\n");
                    break;
            }
            break;
        default:
            printk("传入minor错误.\n");
            break;
    }
    return 0;
}

#define CNAME "myleds"                  // 驱动名
const struct file_operations fop = {
    .open = myopen,
    .release = myclose,
    .unlocked_ioctl = myioctl,
};                                      // 文件操作方法结构体
int major = -1;                         // 主设备号
#define DIRNAME "myleds"                // 目录名
struct class *cls = NULL;               // 目录信息结构体
char *fname[COUNT] = {"myled1", "myled2", "myled3"};    // 设备文件名
struct device *dev = NULL;              // 设备文件信息结构体
#define TNODE "myleds"                  // 设备树结点名
struct device_node *dnode = NULL;       // 解析到的结点
char *tname[COUNT] = {"led1", "led2", "led3"};    // 结点的键名

static int __init myled_init(void)
{
    int ret = -1;   //返回值
    int i = 0;      // 循环量

    // 1. 注册字符设备驱动[cdev_alloc >>> cdev_init >>> alloc/register_chrdev_region >>> cdev_add]
    if((major = register_chrdev(0, CNAME, &fop)) < 0)
    {
        printk("注册字符设备驱动[失败].\n");
        ret = major;
        goto ERR1;
    }
    printk("注册字符设备驱动[成功].\n");
    // 2. 向上提交目录信息
    if(IS_ERR(cls = class_create(THIS_MODULE, DIRNAME)))
    {
        printk("向上提交目录信息[失败].\n");
        ret = PTR_ERR(cls);
        goto ERR2;
    }
    printk("向上提交目录信息[成功].\n");
    // 3. 向上提交设备文件信息
    for(i = 0; i < COUNT; i++)
    {    
        if(IS_ERR(dev = device_create(cls, NULL, MKDEV(major, i), NULL, fname[i])))
        {
            printk("向上提交设备文件信息[失败].\n");
            goto ERR3;
            return PTR_ERR(dev);
        }
    }
    printk("向上提交设备文件信息[成功].\n");

    // 1. 解析设备树结点
    if(NULL == (dnode = of_find_node_by_name(NULL, TNODE)))
    {
        printk("解析设备树结点[失败].\n");
        return -ENODATA;
    }
    printk("解析设备树结点[成功].\n");
    // 2. 获取gpio编号
    for(i = 0; i < COUNT; i++)
    {
        if(IS_ERR(gpionum[i] = gpiod_get_from_of_node(dnode, tname[i], 0, GPIOD_OUT_LOW, NULL)))
        {
            printk("获取gpio编号[失败].\n");
            ret = -PTR_ERR(gpionum[i]);
            goto ERR4;
        }
    }
    printk("获取gpio编号[成功].\n");
    // 3. 测试
    for(i = 0; i < COUNT; i++)
    {
        gpiod_set_value(gpionum[i], 1);
    }
    printk("测试完成.\n");
    return 0;

    ERR4:
        for(--i; i >= 0; i--)
        {
            gpiod_put(gpionum[i]);
        }
        i = COUNT;
    ERR3:
        for(--i; i >= 0; i--)
        {
            device_destroy(cls, MKDEV(major, i));
        }
        class_destroy(cls);
    ERR2:
        unregister_chrdev(major, CNAME);
    ERR1:
    return ret;
}
static void __exit myled_exit(void)
{
    int i = 0;// 循环量

    // 灭灯+释放编号
    for(i = 0; i < COUNT; i++)
    {
        gpiod_set_value(gpionum[i], 0);
        gpiod_put(gpionum[i]);
    }

    // 3. 移除设备文件信息
    for(i = 0; i < COUNT; i++)
    {
        device_destroy(cls, MKDEV(major, i));
    }
    // 2. 移除目录信息
    class_destroy(cls);
    // 1. 注销字符设备驱动
    unregister_chrdev(major, CNAME);
    return ;
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");

 Makefile

KERNDIR:=/home/hades/linux-5.10.61
obj-m:=homework.o
PWD:=$(shell pwd)
all:
	make -C $(KERNDIR) M=$(PWD) modules
clean:
	make -C $(KERNDIR) M=$(PWD) clean

 testForLed.c

#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include "homework.h"

int main(int argc, const char *argv[])
{
    int fds[3] = {0};
    char *devname[3] = {"/dev/myled1", "/dev/myled2", "/dev/myled3"};

    for(int i = 0; i < 3; i++)
    {
        if(-1 == (fds[i] = open(devname[i], O_RDWR)))
        {
            perror("open");
            return -1;
        }
    }
    printf("文件打开完毕.\n");
    char cmd = 0;
    while(1)
    {
        puts("MENU");
        puts("0. QUIT");
        puts("1. LED1_ON");
        puts("2. LED2_ON");
        puts("3. LED3_ON");
        puts("4. LED1_OFF");
        puts("5. LED2_OFF");
        puts("6. LED3_OFF");
        scanf("%c", &cmd);
        printf("您输入的是:%c\n", cmd);
        switch(cmd)
        {
            case '0':
                for(int i = 0; i < 3; i++)
                {
                    close(fds[i]);
                }
                return 0;
            case '1':
                ioctl(fds[0], LED1_ON);
                break;
            case '2':
                ioctl(fds[1], LED2_ON);
                break;
            case '3':
                ioctl(fds[2], LED3_ON);
                break;
            case '4':
                ioctl(fds[0], LED1_OFF);
                break;
            case '5':
                ioctl(fds[1], LED2_OFF);
                break;
            case '6':
                ioctl(fds[2], LED3_OFF);
                break;
            default:
                printf("请输入正确的cmd.\n");
                break;
        }
        getchar();
        puts("键入回车继续-");
        while(getchar() != 10);
        system("clear");
    }
    return 0;
}

运行截图:

 

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

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

相关文章

【Hive】Hive开启远程连接及访问方法

写在前面&#xff1a;博主是一只经过实战开发历练后投身培训事业的“小山猪”&#xff0c;昵称取自动画片《狮子王》中的“彭彭”&#xff0c;总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域&#xff0c;如今终有小成…

UE5关于高亮显示物体轮廓线

描边材质如果是透明的话&#xff0c;不会显示描边&#xff0c;材质参数勾选【允许自定义深度写入】即可 材质参考这个文章&#xff1a;https://blog.csdn.net/Axiang_0123/article/details/121168272?ops_request_misc&request_id&biz_id102&utm_termUE%E6%9D%90…

多元分类预测 | Matlab灰狼算法(GWO)优化极限学习机(ELM)的分类预测,多特征输入模型。GWO-ELM分类预测模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | 灰狼算法(GWO)优化极限学习机(ELM)的分类预测,多特征输入模型。GWO-ELM分类预测模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可出…

STM32 HAL库手动配置过程

手动配置HAL库与配置固件库工程类似 1、首先新建四个文件夹 2、打开keil5&#xff0c;新建新工程在Project文件夹中 按开发板选择芯片 3、添加hal相关库到工程目录Libraries下 4、在User下新建main.c 5、在工程配置中新建5个组 6、将对应文件添加到工程中 添加启动文件到STAR…

MacPro M2 vscode 配置JAVA开发环境(1)

MacPro 使用vscode 配置Java开发环境 1.vscode 下载2. 安装 Mac 自己的芯片据说已经迭代到M3了&#xff0c;作为一名从windows转mac的小白&#xff0c;本文记录下在mac 中使用vscode开发的环境配置。 1.vscode 下载 对于开源项目&#xff0c;奉行官网优先的原则。 所以先去官…

苹果再施手段,iPhoneX停止升级iOS,迫使用户选购新iPhone

iPhone14不好卖&#xff0c;这段时间大举降价&#xff0c;最高降幅一度达到2000元&#xff0c;不过或许是降价并未能有效拉动销量&#xff0c;苹果如今还采取另一种措施&#xff0c;停止对旧款iPhone的支持&#xff0c;迫使消费者选购新iPhone。 据悉苹果新推出的iOS17操作系统…

STM32 HAL 库驱动 ESP8266 WiFi 模块

STM32 HAL 库驱动 ESP8266 WiFi 模块 实验原理 关于 ESP8266 WiFi 模块使用原理可以看我前面的博客 WiFi 驱动代码连接将会放到文末 这里我们将芯片换为 STM32F103ZET6&#xff0c;别问为什么&#xff0c;问就是引脚资源多 CubeMX 配置 USART2 与 USART3 配置 这里我们使用的配…

chatgpt赋能python:Python解ODE:优雅地解决微分方程

Python解ODE&#xff1a;优雅地解决微分方程 介绍 ODE&#xff08;Ordinary Differential Equation&#xff0c;常微分方程&#xff09;是数学中一个核心领域。为了求解ODE&#xff0c;需要一些高深的数学知识和专业的工具。然而&#xff0c;如果你是一位Python程序员&#x…

RuntimeError: expected scalar type Long but found Float报错解决

在torch模型转onnx模型&#xff0c;我会生成一个随机序列&#xff0c;通过模型预测看输出的维度是否一致吗但是遇到这个报错 我是这样生成的 dummy_input torch.randn(1,1,1200) dummy_output model_pytorch(dummy_input) print(dummy_output.shape) RuntimeError: expec…

SpringBoot基于Mybatis或Mybatis-Plus自定义实现完整SQL打印和执行耗时

注释相当完善了&#xff0c;不啰嗦。直接上代码&#xff1a; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import org.apache.ibatis.executor.parameter.ParameterHandler; impor…

移远通信率先完成5G RedCap运营商实网测试,为商用部署奠定良好基础

近日&#xff0c;移远通信Rx255C 5G RedCap系列模组在上海率先完成了运营商RedCap实网环境下的测试&#xff0c;并成功验证了RedCap网络接入等一系列能力&#xff0c;为加速RedCap在中高速物联网领域的商用部署奠定了良好的基础。 位于上海市嘉定区的RedCap实网测试现场 本次外…

​价值驱动-数据分析价值逻辑与实践思考

月説小飞象交流会 未来是一片迷雾&#xff0c;令人胆怯&#xff0c;但不妨走下去&#xff0c;看看命运给我们准备了什么。 内部交流│25期 价值驱动 数据分析价值逻辑与实践思考 data analysis ●●●● 分享人&#xff1a;黄小伟 当今的企业&#xff0c;随着数字化技术日新月异…

机器学习——深度学习

1 感知机 y f ( ∑ i 1 n w i x i − b ) yf(\sum\limits_{i1}^{n}w_ix_i-b) yf(i1∑n​wi​xi​−b) 其中&#xff0c; f f f 常常取阶跃函数或 Sigmoid 函数。 学习规则&#xff1a; Δ w i η ( y − y ^ ) x i w i ← w i Δ w i \Delta w_i\eta(y-\hat{y})x_i\\ w_i…

C高级重点

1、请简要描述一下Linux文件系统的层级结构&#xff0c;包括不同目录的作用和功能。 Linux的文件系统结构是一个倒插树结构&#xff0c;所有的文件都从根目录出发。 2、find指令的用途 find 查找的路径 -name 文件名 ----->在指定路径下&#xff0c;以文件名为条件查找文…

windows gcc、g++和cmake安装

1、gcc gwindows版本工具mingw下载安装 参考&#xff1a;https://blog.csdn.net/didi_ya/article/details/111240502 https://blog.csdn.net/weixin_46416035/article/details/127387170 ##看这个 下载&#xff1a; https://sourceforge.net/projects/mingw-w64/files/mingw…

图书搜索领域重大突破!用Apache SeaTunnel、Milvus和OpenAI提高书名相似度搜索精准度和效率

作者 | 刘广东&#xff0c;Apache SeaTunnel Committer 背景 目前&#xff0c;现有的图书搜索解决方案&#xff08;例如公共图书馆使用的解决方案&#xff09;十分依赖于关键词匹配&#xff0c;而不是对书名实际内容的语义理解。因此会导致搜索结果并不能很好地满足我们的需…

nodejs安装记录

1.更改安装目录 D:\env\nodejs 2.命令行输入 node -v 查看nodejs的版本号 3.命令行输入 npm -v查看npm的版本号 4.修改模块安装和缓存路径 之前的设置&#xff1a; 在nodejs安装目录下新建一个文件夹&#xff0c;命名为 node_cache 使用命令修改config配置&#xff0c;首先…

【超简单】Windows 使用 mstsc 远程连接 Ubuntu桌面

登录网站下载 《xrdp-installer-1.4.7.zip》 xRDP Installation Script (free)&#xff1a;https://c-nergy.be/repository.html 在Ubuntu 下&#xff0c;解压&#xff0c;添加x 权限后执行安装 chmod 777 xrdp-installer-1.4.7.sh ./xrdp-installer-1.4.7.sh安装完毕后&…

【嵌入式模型转换】2. 算能盒子SE5 芯片板子BM1684 sophon-pipeline

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1. 开始安装 前言 文章1&#xff0c;我们在SE5上实现了&#xff0c;SOC模式下的 C 和 python-sail的模型转换&#xff0c;文章连接&#xff1a; 【嵌入式模型转…

VUE L ∠脚手架新生命周期过度动画 ⑩⑦

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs初识 V u e C L I VueCLI VueCLI C L I CLI CLI n e x t T i c k nextTick nextTick C L I CLI CLI V u e Vue Vue封装的过度与动画 C L I CLI …