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…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
