驱动day10作业

news2024/11/19 5:53:28

基于platform驱动模型完成LED驱动的编写

驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include<linux/platform_device.h>
#include<linux/mod_devicetable.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"

int major;   //字符设备驱动注册主设备号
struct class *cls;    //向上提交目录
struct device *dev;   //向上提交设备节点
struct gpio_desc* gpiono[3];

//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
	printk("%s:%s:%d\n", __FILE__,__func__,__LINE__);
	return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int which;
	int ret = copy_from_user(&which, (void*)arg,4); 
	if(ret)
	{
		printk("copy_from_user failed\n");
		return -EIO;
	}
	switch(cmd)
	{
		case LED_ON:
			switch(which)
			{
				case 1:
					gpiod_set_value(gpiono[0],1);
					break;
				case 2:
					gpiod_set_value(gpiono[1], 1);
					break;
				case 3:
					gpiod_set_value(gpiono[2], 1);
					break;
			}
			break;
		case LED_OFF:
			switch(which)
			{
				case 1:
					gpiod_set_value(gpiono[0],0);
					break;
				case 2:
					gpiod_set_value(gpiono[1], 0);
					break;
				case 3:
					gpiod_set_value(gpiono[2], 0);
					break;
			} 
			break;
	}

	printk("%s:%s:%d\n", __FILE__,__func__,__LINE__);
	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,
	.unlocked_ioctl = mycdev_ioctl,
	.release = mycdev_close,
};

int pdrv_probe(struct platform_device *pdev)//当驱动和设备匹配成功之后执行
{
	//字符设备驱动注册
	major = register_chrdev(0, "mycdev",&fops);
	if(major < 0)
	{
		printk("字符设备驱动注册失败\n");
		return major;
	}
 
	/****************************udev创建设备节点的原************************/
	//向上提交目录
	cls = class_create(THIS_MODULE, "mycdev");
	if(IS_ERR(cls))
	{
		printk("向上提交目录失败\n");
		return -PTR_ERR(cls); 
	}
	//向上提交设备节点信息
	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");
            return -PTR_ERR(dev);
        }
	}
	printk("向上提交设备节点成功\n");


	//解析LED设备树节点获取三个节点的gpio信息
	for(i=0; i<3; i++)
	{
		gpiono[i]=gpiod_get_from_of_node(pdev->dev.of_node,"led-gpios", i, GPIOD_OUT_HIGH, NULL);
		if(IS_ERR(gpiono[i]))
		{
			printk("解析GPIO信息失败\n");
			return -PTR_ERR(gpiono[i]);
		}
		printk("解析GPIO信息成功\n");
	}
	return 0;
}

int pdrv_remove(struct platform_device *pdev)
{
	int i;
	for(i=0; i<3; i++)
	{
	gpiod_set_value(gpiono[i], 0);
	
	//释放gpio编号
	gpiod_put(gpiono[i]);
	//销毁设备节点信息
	device_destroy(cls, MKDEV(major, i));
	}
	
	//销毁目录
	class_destroy(cls);
	//注销字符设备驱动
	unregister_chrdev(major, "mycdev");
	return 0;
}
//构建设备树匹配表
struct of_device_id oftable[] = {
	{.compatible="hqyj,myplatform",},
	{.compatible="hqyj,myplatform1",},
	{},   //防止数组越界
};
//1分配驱动信息对象
struct platform_driver pdrv= {
	.probe=pdrv_probe,
	.remove=pdrv_remove,
	.driver={
		.name="bbbbb",   //驱动名
		.of_match_table=oftable,
	},
};

//驱动端一键注册宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

应用程序

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

int main(int argc, char const *argv[])
{
    int fd = open("/dev/myled0", O_RDWR);
    if(fd < 0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        int a;
        printf("请输入1(开灯)0(关灯)>>");
        scanf("%d", &a);
        int b;
        printf("请输入 1(LED1) 2(LED2) 3(LED3)>>");
        scanf("%d", &b);
    
        switch(a)
        {
            case 1:
                ioctl(fd, LED_ON,&b);
                break;
            case 0:
                ioctl(fd, LED_OFF,&b);
                break; 
        }
    }
    close(fd);
    return 0;
}

head.h

#ifndef __HEAD_H__
#define __HEAD_H__
#define LED_ON _IOW('l', 1, int)
#define LED_OFF _IOW('l',0, int)
#endif

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

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

相关文章

本地部署 ChatGLM3

本地部署 ChatGLM3 ChatGLM3 介绍ChatGLM3 Github 地址部署 ChatGLM3运行综合 Demo对话模式工具模式代码解释器模式 API 部署 ChatGLM3 介绍 ChatGLM3 是智谱AI和清华大学 KEG 实验室联合发布的新一代对话预训练模型。ChatGLM3-6B 是 ChatGLM3 系列中的开源模型&#xff0c;在…

(四)docker:为mysql和java jar运行环境创建同一网络,容器互联

看了很多资料&#xff0c;说做互联的一个原因是容器内ip不固定&#xff0c;关掉重启后如果有别的容器启动&#xff0c;之前的ip会被占用&#xff0c;所以做互联创建一个网络&#xff0c;让几个容器处于同一个网络&#xff0c;就可以互联还不受关闭再启动ip会改变的影响&#xf…

C++的拷贝构造函数

目录 拷贝构造函数一、为什么用拷贝构造二、拷贝构造函数1、概念2、特征1. 拷贝构造函数是构造函数的一个重载形式。2. 拷贝构造函数的参数3. 若未显式定义&#xff0c;编译器会生成默认的拷贝构造函数。4. 拷贝构造函数典型调用场景 拷贝构造函数 一、为什么用拷贝构造 日期…

FedGNN: Federated Graph Neural Network for Privacy-Preserving Recommendation

FedGNN&#xff1a;用于隐私保护推荐的联邦图神经网络 参考笔记 ICML-21-workshop 本文的主要创新工作 在具有局部差分隐私的模型训练中保护模型梯度&#xff0c;并提出一种伪交互项目采样技术来保护用户与之交互的项目。提出了一种保护隐私的用户-项目图扩展方法&#xff0…

函数总结

一、main函数 //argc 统计命令行传参的个数 //argv 保存命令行传的具体参数,每个参数当做字符串来存储&#xff0c;const是为了不让main函数修改argv数组里的内容 1.1值传递 此为值传递;形参的值改变不影响实参的值 1.2 地址传递 形参拿到的是实参的地址&#xff0c;实际操…

2023云曦秋季期中考

web 1z_php 看到有点晕&#xff0c;根本分不清0和o <?php // Yeedo told you to study hard! echo !(!(!(include "flag.php"|| (!error_reporting(0))|| !isset($_GET[OoO])|| !isset($_GET[0o0])|| ($_GET[OoO] 2023) //检查 "OoO" 参数是否等于…

使用simple_3dviz进行三维模型投影

【版权声明】 本文为博主原创文章&#xff0c;未经博主允许严禁转载&#xff0c;我们会定期进行侵权检索。 更多算法总结请关注我的博客&#xff1a;https://blog.csdn.net/suiyingy&#xff0c;或”乐乐感知学堂“公众号。 本文章来自于专栏《Python三维模型处理基础》的系列文…

Linux———— 运算命令

Shell与其他编程语言一样&#xff0c;支持多种类型的运算符&#xff0c;包括&#xff1a; 算术运算符&#xff1a;用于执行数学运算&#xff0c;例如加法、减法、乘法和除法。 关系运算符&#xff1a;用于比较两个值之间的关系&#xff0c;例如相等、大于、小于等。 布尔运算…

Vue路由(router)的安装和使用

Vue路由&#xff08;router&#xff09;的安装和使用 安装vue-router插件 第一步&#xff1a;在CMD窗口中&#xff0c;使用命令跳转到vue的安装路径下第二步&#xff1a;输入命令&#xff1a;npm i vue-router3 vue2 要安装 vue-router3 npm i vue-router3 vu3 要安装 vue-ro…

AI绘画|midjourney入门保姆教程,30秒出专业大片,国内直接使用

同学们&#xff0c;之前大家想用midjourney还需要魔法上网和很复杂的注册配置&#xff0c;现在微信里就能使用midjourney了&#xff0c; 还支持中文&#xff0c;大家赶紧来试试吧。 AI写稿专家 www.promptspower.comhttp://www.promptspower.com 我们还给大家提供了各个行业的…

【C++】多态 ⑧ ( 验证指向 虚函数表 的 vptr 指针 | 对比定义了虚函数的类和没有定义虚函数类的大小 )

文章目录 一、验证指向 虚函数表 的 vptr 指针 是否存在1、虚函数表与 vptr 指针由来2、虚函数类与普通函数类对比 - 多出了 vptr 指针的大小 对比 定义了 虚函数 的类 与 没有定义虚函数的类 的大小 , 其它成员都相同 , 定义了虚函数的类多出了 4 字节 , 多出的 4 字节就是 vp…

MES 的价值点之动态调度

随着数字化技术的发展&#xff0c;为制造企业的生产计划提供了更多的便利。但在实际生产管理过程中&#xff0c;企业的生产计划不管做的多么理想&#xff0c;还是可能会因诸多的扰动因素造成执行与计划差异&#xff0c;这时就需要通过一些动态调整方案去适应新的生产要求与环境…

OSPF复习(2)

目录 一、LSA的头部 二、6种类型的LSA&#xff08;课堂演示&#xff09; 1、type1-LSA&#xff1a;----重要且复杂 2、type2-LSA&#xff1a; 3、type3-LSA&#xff1a; 4、type4-LSA&#xff1a; 5、type5-LSA&#xff1a; 6、type7-LSA&#xff1a; 三、OSPF的网络类…

narak靶机攻略

narak靶机攻略 扫描 渗透 cewl http://10.4.7.158 > use1.txthydra -L use1.txt -P use1.txt http-get://10.4.7.158/webdav -V -t 50 -fyamdoot:Swargcadaver http://10.4.7.158/webdav<?php $ip10.4.7.158; $port12138; $sock fsockopen($ip, $port); $descriptors…

JVM虚拟机:如何调整堆空间的大小?

对内存的调优 如上所示,从物理角度来说呢,堆内存就是蓝色的区域,从逻辑角度来说,堆内存包含这个红色的部分,调优肯定是条物理的大小了,我们先来看一下物理内存的大小是多少? 如上所示,我们通过maxMemory获取到java虚拟机试图使用的最大内存量,默认为物理内存的1/4,比我…

Lec11 Thread switching (Robert)

线程的概念 线程就是单个串行执行代码的单元&#xff0c;它只占用一个CPU并且以普通的方式一个接一个的执行指令。 线程还具有状态&#xff0c;我们可以随时保存线程的状态并暂停线程的运行&#xff0c;并在之后通过恢复状态来恢复线程的运行。 程序计数器&#xff08;Progr…

精品基于Python的个性化电影推荐系统

《[含文档PPT源码等]精品基于Python的个性化电影推荐系统设计与实现》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技…

AutoX.js - openCV多分辨率找图

AutoX.js - openCV多分辨率找图 一、起因 AutoXjs 中有两个找图相关的方法 findImage 和 matchTemplate&#xff0c;之前一直没发现什么问题&#xff0c;但最近在一次测试找图时&#xff0c;明明大图和模板图的轮廓都清晰&#xff0c;却怎么也找不到图&#xff0c;降低阈值参…

【数据结构】顺序表实例探究

&#x1f497;个人主页&#x1f497; ⭐个人专栏——数据结构学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读&#xff1a;1. 顺序表的基本内容1.1 概念及结构1.2 时间和空间复杂度1.3 基本操作1.4 顺序表的优缺点 2. 静态顺序表…

CVPR 2023 | 主干网络FasterNet 核心解读 代码分析

本文分享来自CVPR 2023的论文&#xff0c;提出了一种快速的主干网络&#xff0c;名为FasterNet。 论文提出了一种新的卷积算子&#xff0c;partial convolution&#xff0c;部分卷积(PConv)&#xff0c;通过减少冗余计算和内存访问来更有效地提取空间特征。 创新在于部分卷积…