platform(驱动层+应用层)实现终端和中断开关点灯
设备树文件添加
myplatform{compatible="hqyj,myplatform";interrupt-parent=<&gpiof>;interrupts=<8 0>,<7 0>,<9 0>;led1-gpio=<&gpioe 10 0>;led2-gpio=<&gpiof 10 0>;led3-gpio=<&gpioe 8 0>;reg=<0x12345678 0x400>;};
应用层
#include<stdio.h>
#include<stdlib.h>
#include<string.h>#include<fcntl.h>
#include<unistd.h>#include<sys/types.h>
#include<sys/stat.h>
#include<sys/ioctl.h>#include"head.h"int main(int argc, char const *argv[])
{int fd;int devc;//设备的编号char buf[128];printf("选择需要打开的设备文件(led)>>");//配置需要打开的设备文件scanf("%d",&devc);sprintf(buf,"/dev/myled%d",devc);printf("路径为:%s",buf);fd=open(buf,O_RDWR);if (fd<0){printf("文件打开失败\n");return -1;}printf("设备文件打开成功\n");int a,b;//输入的值while (1){out:printf("选择需要打开的灯led 1 led 2 led 3>>");scanf("%d",&a);printf("选择要实现的功能 0 关 1开>>");scanf("%d",&b);switch (b){case 0:ioctl(fd,LED_OFF,a); break;case 1:ioctl(fd,LED_ON,a); break;default:printf("输入错误请重新输入\n");goto out;break;}}return 0;
}
头文件
#ifndef __HEAD_H__
#define __HEAD_H__#define LED_ON _IOW('l',1,int)
#define LED_OFF _IOW('l',0,int)
#endif
设备层
#include <linux/init.h>
#include <linux/module.h>#include<linux/fs.h>
#include<linux/io.h>
#include<linux/device.h>#include<linux/gpio.h>
#include<linux/of.h>
#include<linux/of_gpio.h>#include"head.h"#include <linux/platform_device.h>void pdev_release(struct device *dev)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
}
struct resource res[]={[0]={.start=0x50006000,//起始地址.end=0x50006000+0x400,//终止地址.name="pe_mem",//名字.flags=IORESOURCE_MEM ,//标志位地址空间},[1]={.start=71,.end=71,.name="key1_irq",.flags=IORESOURCE_IRQ,},[2]={.start=72,.end=72,.name="key2_irq",.flags=IORESOURCE_IRQ,},[3]={.start=73,.end=73,.name="key3_irq",.flags=IORESOURCE_IRQ,},
};
//设备结构体
struct platform_device pdev={.name="aaaaa",.id=PLATFORM_DEVID_AUTO,.dev={.release=pdev_release,},.num_resources=ARRAY_SIZE(res),.resource=res,
};
static int __init mycdev_init(void)
{platform_device_register(&pdev);return 0;
}
static void __exit mycdev_exit(void)
{platform_device_unregister(&pdev);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
驱动层
#include <linux/init.h>
#include <linux/module.h>#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>#include <linux/interrupt.h>
#include"head.h"struct resource *res;
unsigned int irq_no[3];int major;
char kbuf[128]={0};struct class *cls;
struct device *dev_c;struct device_node *dnode;struct gpio_desc *lednode1;
struct gpio_desc *lednode2;
struct gpio_desc *lednode3;int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);unsigned long ret;//向用户空间读取拷贝if(size>sizeof(kbuf))//用户空间期待读取的大小内核满足不了,那就给内核支持的最大大小size=sizeof(kbuf);ret=copy_to_user(ubuf,kbuf,size);if(ret)//拷贝失败{printk("copy_to_user filed\n");return ret;}return 0;
}ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{unsigned long ret;//从用户空间读取数据if(size>sizeof(kbuf))//用户空间期待读取的大小内核满足不了,那就给内核支持的最大大小size=sizeof(kbuf);ret=copy_from_user(kbuf,ubuf,size);if(ret)//拷贝失败{printk("copy_to_user filed\n");return ret;}return 0;
}long mycdev_ioctl (struct file * file, unsigned int cmd, unsigned long arg)
{switch (cmd){case LED_OFF:switch (arg){case 1:gpiod_set_value(lednode1,0);break;case 2:gpiod_set_value(lednode2,0);break;case 3:gpiod_set_value(lednode3,0);break;}break;case LED_ON:switch (arg){case 1:gpiod_set_value(lednode1,1);break;case 2:gpiod_set_value(lednode2,1);break;case 3:gpiod_set_value(lednode3,1);break;}break;default:break;}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,.read=mycdev_read,.write=mycdev_write,.unlocked_ioctl=mycdev_ioctl,.release=mycdev_close,
};irqreturn_t myirq_handle(int irq,void *dev)
{switch ((unsigned int)dev){case 0://反转电平gpiod_set_value(lednode1,!gpiod_get_value(lednode1));//防止其他灯亮gpiod_set_value(lednode2,0);gpiod_set_value(lednode3,0);break;case 1://反转电平gpiod_set_value(lednode2,!gpiod_get_value(lednode2));//防止其他灯亮gpiod_set_value(lednode1,0);gpiod_set_value(lednode3,0);break;case 2://反转电平gpiod_set_value(lednode3,!gpiod_get_value(lednode3));//防止其他灯亮gpiod_set_value(lednode1,0);gpiod_set_value(lednode2,0);break;default:break;}return IRQ_HANDLED;}int pdrv_probe(struct platform_device *dev)
{printk("%s:%s:%d",__FILE__,__func__,__LINE__);//字符设备驱动注册major=register_chrdev(0,"mychrdev",&fops);if(major<0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n",major);//向上提交目录cls=class_create(THIS_MODULE,"mychrdev");if(IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录成功\n");int i;for(i=0;i<3;i++){dev_c=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);//制作字符设备文件if(IS_ERR(dev_c)){printk("向上提交设备节点失败\n");return -PTR_ERR(dev_c);}}printk("向上提交设备节点成功\n");res=platform_get_resource(dev,IORESOURCE_MEM,0);if(res==NULL){printk("获取MEM类型资源失败\n");return -EFAULT;} printk("MEM类型资源为%x\n",res->start);//获取中断类型的资源for ( i = 0; i < 3; i++){irq_no[i]=platform_get_irq(dev,i);if (irq_no[i]<0){printk("获取中断类型资源失败\n");return irq_no[i];}printk("获取中断类型资源值为%d\n",irq_no[i]);}//解析LED1的gpio编号lednode1=gpiod_get_from_of_node(dev->dev.of_node,"led1-gpio",0,GPIOD_OUT_LOW,NULL);if (lednode1==NULL){printk("解析gpio编号失败\n");return -ENXIO;}lednode2=gpiod_get_from_of_node(dev->dev.of_node,"led2-gpio",0,GPIOD_OUT_LOW,NULL);if (lednode2==NULL){printk("解析gpio编号失败\n");return -ENXIO;}lednode3=gpiod_get_from_of_node(dev->dev.of_node,"led3-gpio",0,GPIOD_OUT_LOW,NULL);if (lednode3==NULL){printk("解析gpio编号失败\n");return -ENXIO;}printk("解析gpio-led编号成功\n");for ( i = 0; i < 3; i++){irq_no[i]=irq_of_parse_and_map(dev->dev.of_node,i);if(!irq_no[i]){printk("解析软中断失败\n");return -ENXIO;}printk("解析%d 软中断成功\n",i+1);int ret=request_irq(irq_no[i],myirq_handle,IRQF_TRIGGER_FALLING,"key",(void*)i); if(ret){printk("注册按键请求中断失败\n");return ret;}}printk("注册按键请求中断成功\n");return 0;
}int pdrv_remove(struct platform_device *dev)
{gpiod_set_value(lednode1,0);gpiod_put(lednode1);gpiod_set_value(lednode2,0);gpiod_put(lednode2);gpiod_set_value(lednode3,0);gpiod_put(lednode3);int i;
for ( i = 0; i < 3; i++)
{free_irq(irq_no[i],(void*)i);device_destroy(cls,MKDEV(major,i));
}//销毁目录class_destroy(cls);//注销字符设备驱动unregister_chrdev(major,"mychrdev");printk("%s:%s:%d",__FILE__,__func__,__LINE__);return 0;
}struct of_device_id oftable[]=
{{.compatible="hqyj,myplatform",},{/*end node*/},//防止数组越界
};struct platform_driver pdrv={.probe=pdrv_probe,.remove=pdrv_remove,.driver={.name="bbbbb",.of_match_table=oftable,//设置设备树匹配},};module_platform_driver(pdrv);
MODULE_LICENSE("GPL");
现象演示

相关文章:
platform(驱动层+应用层)实现终端和中断开关点灯
设备树文件添加 myplatform{compatible"hqyj,myplatform";interrupt-parent<&gpiof>;interrupts<8 0>,<7 0>,<9 0>;led1-gpio<&gpioe 10 0>;led2-gpio<&gpiof 10 0>;led3-gpio<&gpioe 8 0>;reg<0x123…...
黑马JavaWeb开发跟学(一)Web前端开发HTML、CSS基础
黑马JavaWeb开发一.Web前端开发HTML、CSS基础 引子、Web开发介绍传统路线本课程全新路线本课程适用人群课程收获一、什么是web开发二、网站的工作流程三、网站的开发模式四、网站的开发技术 前端开发基础一、前端开发二、HTML & CSS2.1 HTML快速入门2.1.1 操作第一步第二步…...
Nest.js权限管理系统开发(四)Swagger API接入
什么是swagger Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(<https://swagger.io/>)。 它的主要作用是: 1. 使得前后端分离开发更加方便,有利于团队协作 2. 接口的文档在线自动生成…...
(全注解开发)学习Spring-MVC的第三天
全注解开发 第一部分 : 1.1 消除spring-mvc.xml 这些是原来spring-mvc.xml配置文件的内容 <!--1、组件扫描, 使Controller可以被扫描到--><context:component-scan base-package"com.itheima.controller"/><!--2、非自定义的Bean, 文件上传解析器--&…...
设计模式学习笔记 - 面向对象 - 7.为什么要多用组合少用继承?如何决定该用组合还是继承?
前言 在面向对象编程中,有一条非常经典的设计原则:组合优于继承,多用组合少用继承。 为什么不推荐使用继承? 组合比继承有哪些优势? 如何判断该用组合还是继承? 为什么不推荐使用继承? 继承…...
RocketMQ生产环境常见问题分析与总结
RocketMQ生产环境常见问题分析与总结 如何保证消息不丢失 消息丢失场景 对于跨网络的节点可能会丢消息,因为MQ存盘都会先写入OS的PageCache中,然后再让OS进行异步刷盘,如果缓存中的数据未及时写入硬盘就会导致消息丢失 生产端到Broker端Brok…...
前端打包工具的发展历程、思路(grunt,gulp,webpack,vite)
现在前端发展真快,需要学的东西太多了,下面总结下前端打包的发展过程,便于区分和选择学习。 什么是前端打包 前端打包是指将多个JavaScript文件、CSS文件、图片等资源进行合并和优化处理,并输出为一个或多个文件的过程。这样做的目的是减少…...
利用Python将文件夹下多个txt文本写入到同一个excel中(每一个文件占一行)
1、 将文件夹下多个txt文本写入到同一个excel中(每一个文件占一行): # -*- coding: utf-8 -*- import os import pandas as pd# 获取文件夹中的所有txt文件 folder_path rG:\Cygwin\ txt_files [f for f in os.listdir(folder_path) if f.endswith(.t…...
通过Colab部署Google最新发布的Gemma模型
Gemma的简单介绍 Gemma 是一系列轻量级、最先进的开放式模型,采用与创建 Gemini 模型相同的研究和技术而构建。 Gemma 由 Google DeepMind 和 Google 的其他团队开发,其灵感来自 Gemini,其名称反映了拉丁语 gemma,意思是“宝石”…...
spring中@validate注解使用
在 Java 中,我们可以使用注解和 validate 实现对实体类中字段的校验。其中,注解用来定义字段的约束条件,而 validate 则用来进行实际的校验操作。 常用的校验注解包括 NotNull、NotEmpty、Size、Min、Max 等,它们可以帮助我们规定…...
停车场管理(C语言)
【题目描述】停车场管理。设有一个可以停放n辆汽车的狭长停车场,它只有一个大门可以供车辆进出。车辆按到达停车场时间的先后次序依次从停车场最里面向大门口处停放 (即最先到达的第一辆车停放在停车场的最里面) 。如果停车场已放满n辆车,则以后到达的车…...
探索无限:Sora与AI视频模型的技术革命 - 开创未来视觉艺术的新篇章
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua,在这里我会分享我的知识和经验。&#x…...
375FPS! 谷歌提出MaskConver“重校正用于全景分割的纯卷积模型
https://arxiv.org/2312.06052 近年来,基于Transformer的模型由于其强大的建模能力以及对语义类和实例类的统一表示为全局二值掩码,在全景分割中占据主导地位。 在本文中,我们回顾了纯粹的卷积模型,并提出了一种新的结构MaskConve…...
leetcode初级算法(python)- 数组
文章目录 1.从排序数组中删除重复项2.买卖股票最佳时机23.旋转数组运行颠倒列表法整体移动元素块法4.存在重复运行包含判断法排序比较判断法运行集合判断法5.只出现一次的数字6.两个数组的交集27.移动零8.两数之和9.旋转图像这篇博客中的代码都是数组计算。 1.从排序数组中删除…...
重新定义音乐创作:ChatGPT与未来音乐产业的融合
### 重新定义音乐创作:ChatGPT与未来音乐产业的融合 随着人工智能技术的飞速发展,ChatGPT不仅在文字创作领域大放异彩,也正逐步渗透并重塑音乐产业的未来。这种先进的语言模型,如今已成为音乐家、作曲家和制作人们手中的一把利剑…...
人工智能绘画的时代下到底是谁在主导,是人类的想象力,还是AI的创造力?
#ai作画 目录 一.AI绘画的概念 1. 数据集准备: 2. 模型训练: 3. 生成绘画: 二.AI绘画的应用领域 三.AI绘画的发展 四.AI绘画背后的技术剖析 1.AI绘画的底层原理 2.主流模型的发展趋势 2.1VAE — 伊始之门 2.2GAN 2.2.1GAN相较于…...
[HTML]Web前端开发技术29(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页
希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要! 目录 前言 上一节的课后练习...
文本编辑器markdown语法
markdown语法 1.介绍 Markdown是一种使用一定的语法将普通的文本转换成HTML标签文本的编辑语言,它的特点是可以使用普通的文本编辑器来编写,只需要按照特定的语法标记就可以得到丰富多样的HTML格式的文本。 2.标题分级 "# " -> 一级标题 &…...
【C++】类和对象之拷贝构造函数篇
个人主页 : zxctscl 文章封面来自:艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 传值传参和传引用传参3. 概念4. 特征 1. 前言 在前面学习了6个默认成员函数中的构造函数和析构函数 【C】构造函数和析构函数详解,接下来继续往后看拷…...
Mybatisplus 传参参数为自定义sql, 使用条件构造器作为参数
1 pom依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version> </dependency> 2 mapper 接口文件 List<TBookOrder> searchDiy(Param(Const…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
