当前位置: 首页 > news >正文

【驱动开发】LED灯的亮灭——通过字符设备驱动的分步实现编写LED驱动,实现设备文件和设备的绑定

头文件:

#ifndef __HEAD_H__
#define __HEAD_H__typedef struct
{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR;   
}gpio_t;//LED灯的寄存器地址
#define LED1_ADDR 0X50006000
#define LED2_ADDR 0X50007000
#define LED3_ADDR 0X50006000
#define RCC_ADDR 0X50000A28//构建LED开关的功能码,ioctl第三个参数
#define LED_ON _IO('l',1)
#define LED_OFF _IO('l',0)#endif

驱动程序:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "head.h"
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>struct cdev *cdev = NULL;
unsigned major = 0;
unsigned minor = 0;
module_param(major, uint, 0664);
dev_t devno;
char kbuf[128] = {0};
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
// 定义指针指向映射后的虚拟内存
unsigned int *vir_rcc;
struct class *cls;
struct device *dev;// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{// 设备文件和设备绑定// 获取打开的文件的次设备号int min = MINOR(inode->i_rdev);file->private_data = (void *)min;printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg){int min = (int)file->private_data;switch (min){case 0: // 控制LED1switch (cmd){case LED_ON: // 开灯vir_led1->ODR |= (0x1 << 10);break;case LED_OFF: // 关灯vir_led1->ODR &= (~(0x1 << 10));break;}break;case 1: // 控制LED2switch (cmd){case LED_ON: // 开灯vir_led2->ODR |= (0x1 << 10);break;case LED_OFF: // 关灯vir_led2->ODR &= (~(0x1 << 10));break;}break;case 2: // 控制LED3switch (cmd){case LED_ON: // 开灯vir_led3->ODR |= (0x1 << 8);break;case LED_OFF: // 关灯vir_led3->ODR &= (~(0x1 << 8));break;}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,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};int all_led_init(void)
{// 寄存器地址的映射vir_led1 = ioremap(LED1_ADDR, sizeof(gpio_t));if (vir_led1 == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_led2 = ioremap(LED2_ADDR, sizeof(gpio_t));if (vir_led2 == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_led3 = vir_led1;vir_rcc = ioremap(RCC_ADDR, 4);if (vir_rcc == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}printk("物理地址映射成功\n");// 寄存器的初始化// rcc(*vir_rcc) |= (3 << 4);// led1vir_led1->MODER &= (~(3 << 20));vir_led1->MODER |= (1 << 20);vir_led1->ODR &= (~(1 << 10));// led2vir_led2->MODER &= (~(3 << 20));vir_led2->MODER |= (1 << 20);vir_led2->ODR &= (~(1 << 10));// led3vir_led3->MODER &= (~(3 << 16));vir_led1->MODER |= (1 << 16);vir_led1->ODR &= (~(1 << 8));printk("寄存器初始化成功\n");return 0;
}static int __init mycdev_init(void)
{// 1.申请一个对象空间cdev_allocint ret;cdev = cdev_alloc();if (cdev == NULL){printk("申请字符设备驱动对象失败\n");ret = -EFAULT;goto out1;}printk("字符设备驱动对象申请成功\n");// 2.初始化对象cdev_initcdev_init(cdev, &fops);// 3.申请设备号  register_chrdev_region()/alloc_chrdev_region()if (major == 0) // 动态申请{ret = alloc_chrdev_region(&devno, minor, 3, "mychrdev");if (ret){printk("动态申请设备号失败\n");goto out2;}major = MAJOR(devno); // 根据设备号获取主设备号minor = MINOR(devno); // 根据设备号获取次设备号}else{ret = register_chrdev_region(MKDEV(major, minor), 3, "mychrdev");if (ret){printk("静态指定设备号失败\n");goto out2;}}printk("设备号申请成功\n");// 4.注册驱动对象  cdev_addret = cdev_add(cdev, MKDEV(major, minor), 3);if (ret){printk("注册字符设备驱动对象失败\n");goto out3;}printk("注册字符设备驱动对象成功\n");// 相关寄存器地址映射及初始化all_led_init();// 5.向上提交目录  class_createcls = class_create(THIS_MODULE, "mychrdev");if (IS_ERR(cls)){printk("向上提交目录失败\n");goto out4;}printk("向上提交目录成功\n");// 6.向上提交设备节点信息  device_createint i;for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mycdev%d", i);if (IS_ERR(dev)){printk("向上提交设备节点失败\n");goto out5;}}printk("向上提交设备节点信息成功\n");return 0;
out5:// 将提交成功的节点信息释放for (--i; i >= 0; i--){device_destroy(cls, MKDEV(major, i));}// 销毁目录class_destroy(cls);
out4:cdev_del(cdev);
out3:unregister_chrdev_region(MKDEV(major, minor), 3);
out2:kfree(cdev);
out1:return ret;
}
static void __exit mycdev_exit(void)
{// 1.销毁设备节点信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 2.销毁目录class_destroy(cls);// 3.注销字符设备驱动对象cdev_del(cdev);// 4.释放设备号unregister_chrdev_region(MKDEV(major, minor), 3);// 5.释放申请到的字符设备驱动对象空间kfree(cdev);// 取消物理内存的映射iounmap(vir_led1);iounmap(vir_led2);iounmap(vir_rcc);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

应用程序: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "head.h"
#include <sys/ioctl.h>
int main(int argc, char const *argv[])
{int a;char buf[128] = {0};int fd = open("/dev/mycdev0", O_RDWR);if (fd < 0){printf("打开设备文件失败\n");return -1;}printf("打开设备文件成功\n");while (1){// 从终端读取printf("请输入要实现的功能 ");printf("0(关灯) 1(开灯)\n");printf("请输入>>>");scanf("%d", &a);getchar();switch (a){case 1:ioctl(fd, LED_ON); // 第三个参数为指针break;case 0:ioctl(fd, LED_OFF);break;}}close(fd);return 0;
}

相关文章:

【驱动开发】LED灯的亮灭——通过字符设备驱动的分步实现编写LED驱动,实现设备文件和设备的绑定

头文件&#xff1a; #ifndef __HEAD_H__ #define __HEAD_H__typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t;//LED灯的寄存器地址 #define LED1_ADDR 0X50006000 #define L…...

华为OD 最小数字(100分)【java】A卷+B卷

华为OD统一考试A卷+B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入: 我用夸克网盘分享了「华为O…...

大模型、实时需求推动湖仓平台走向开放

大模型、实时需求高涨 AGI 时代&#xff0c;以 ChatGPT、Midjourney 等为代表的大模型迅速应用加速了 AI 普及&#xff0c;越来越多的企业选择搭建自己的 AI 基础设施&#xff0c;训练行业大模型。 另一方面&#xff0c;企业为了在瞬息万变的市场环境中更快的做出商业决策&…...

Linux搭建文件服务器

搭建简单文件服务器 基于centos7.9搭建http文件服务器基于centos7.9搭建nginx文件服务器基于ubuntu2204搭建http文件服务器 IP环境192.168.200.100VMware17 基于centos7.9搭建http文件服务器 安装httpd [rootlocalhost ~]# yum install -y httpd关闭防火墙以及selinux [roo…...

跨境商城源码可以支持多种支付方式吗?

跨境商城源码是一种用于建立跨国界电商平台的程序代码。随着全球电商的繁荣发展&#xff0c;越来越多的商家开始寻找一种既安全可靠&#xff0c;又能满足用户需求的支付方式。那么&#xff0c;跨境商城源码是否能够支持多种支付方式呢?让我们深入探讨一下。 1. 支付宝支付 支付…...

机器学习中的核方法

一、说明 线性模型很棒&#xff0c;因为它们易于理解且易于优化。他们受苦是因为他们只能学习非常简单的决策边界。神经网络可以学习更复杂的决策边界&#xff0c;但失去了线性模型良好的凸性特性。 使线性模型表现出非线性的一种方法是转换输入。例如&#xff0c;通过添加特征…...

搜索问答技术学习:基于知识图谱+基于搜索和机器阅读理解(MRC)

目录 一、问答系统应用分析 二、搜索问答技术与系统 &#xff08;一&#xff09;需求和信息分析 问答需求类型 多样的数据源 文本组织形态 &#xff08;二&#xff09;主要问答技术介绍 发展和成熟度分析 重点问答技术基础&#xff1a;KBQA和DeepQA KBQA&#xff08;…...

LeetCode2409——统计共同度过的日子数

博主的解法过于冗长&#xff0c;是一直对着不同的案例debug修改出来的&#xff0c;不建议学习。虽然提交成功了&#xff0c;但是自己最后都不知道写的是啥了哈哈哈。 package keepcoding.leetcode.leetcode2409; /*Alice 和 Bob 计划分别去罗马开会。给你四个字符串 arriveA…...

【MyBatisPlus】快速入门、常用注解、常用配置

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 MyBatisPlus 一、快速入门1.1 引入MyBatisP…...

【USRP】通信之:光通信

光通信: 光通信是使用光信号&#xff08;通常是红外或可见光信号&#xff09;在光纤或空气中传输信息的技术。由于光信号的特性&#xff0c;光通信具有非常高的数据传输率和长距离传输能力。以下是光通信的一些关键组件和概念&#xff1a; 光纤&#xff1a; 是由非常纯净的玻璃…...

bpf对内核的观测

目录 1 bpftrace常用命令1.1 列出bpftrace 相关命令的list1. 2bpftrace -e 是执行1.3 查看参数 -lv 2 bpftrace 可以用到的变量3 高级3.1 内置函数3.2 文件系统3.3 内核内存 栈3.4 Malloc 调用 统计3.5 系统调用 brk 的 统计3.6 脚本调用 4 应用5 怎么串联起来呢 bpftrace 总的…...

Tiktok shop api 调试

记录一下调试Tiktok shop api 踩坑记录。 主要是在按官网api上规则和加密生成sign时候一直通不过的问题&#xff1a; 官网地址&#xff1a;https://partner.tiktokshop.com/doc/page/63fd743e715d622a338c4eab 直接贴代码了 import lombok.extern.slf4j.Slf4j;import javax.cr…...

QFSFileEngine::open: No file name specified解决方案

问题 使用QFile类进行文件操作时&#xff0c;报错QFSFileEngine::open: No file name specified。 原因 QFile::open: No file name specified是Qt中的一个错误消息&#xff0c;提示没有指定文件名导致文件无法打开。这个错误通常出现在使用QFile::open()函数时没有提供有效…...

Flappy bird项目

一、功能分析 1、小鸟自动向右滑行 2、按下空格小鸟上升&#xff0c;不按下落 3、显示小鸟需要穿过的管道 4、管道自动左移和创建 5、小鸟和管道碰撞&#xff0c;游戏结束 6、技术 7、 项目框图 8、Ncurses 1&#xff09;创建窗口界面&#xff0c;移动光标&#xff0c;产…...

高校教务系统登录页面JS分析——西安科技大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…...

Mysql 事务的实现原理

Mysql 里面的事务&#xff0c;满足 ACID 特性&#xff0c;所以Mysql 的事务实现原理&#xff0c;就是InnoDB 是如何保证 ACID 特性的。 ACID A 表示 Atomic 原子性&#xff0c;也就是需要保证多个 DML 操作是原子的&#xff0c;要么都成功&#xff0c;要么都失败。那么&#xf…...

使用vscode搭建虚拟机

首先vscode插件安装 名称: Remote - SSH ID: ms-vscode-remote.remote-ssh 说明: Open any folder on a remote machine using SSH and take advantage of VS Codes full feature set. 版本: 0.51.0 VS Marketplace 链接: https://marketplace.visualstudio.com/items?it…...

C# 使用 LibUsbDotNet 实现 USB 设备检测

国庆节回来后的工作内容&#xff0c;基本都在围绕着各种各样的硬件展开&#xff0c;这无疑让本就漫长的 “七天班” &#xff0c;更加平添了三分枯燥&#xff0c;我甚至在不知不觉中学会了&#xff0c;如何给打印机装上不同尺寸的纸张。华为的 Mate 60 发布以后&#xff0c;人群…...

系统安全分析与设计

系统安全分析与设计&#xff08;2分&#xff09; 内容提要 对称加密与非对称加密 加密技术与认证技术 加密技术&#xff08;只能防止第三方窃听&#xff09; 讲解地址&#xff1a;对称加密与非对称加密_哔哩哔哩_bilibili 认证技术 骚戴理解&#xff1a;数字签名是用私钥签名…...

UE4 AI群集实现

逻辑就不用说了&#xff0c;就是计算对应图形位置让每个Pawn移动到该位置 因为有时候AI与AI会卡住 所以加上这个Bool为true&#xff0c;以及设置两个AI之间至少隔的距离&#xff0c;设置在一个合理的参数即可 有时候AI群集&#xff0c;AI与AI会比较紧密&#xff0c;可以将Caps…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...