驱动(分步注册驱动设备)

头文件

#ifndef __LED_H__
#define __LED_H__#define PHY_LED1_MODER 0X50006000
#define PHY_LED1_ODR  0X50006014
#define PHY_LED1_RCC 0X50000A28#define PHY_LED2_MODER 0X50007000
#define PHY_LED2_ODR  0X50007014
#define PHY_LED2_RCC  0X50000A28#define PHY_LED3_MODER 0X50006000
#define PHY_LED3_ODR  0X50006014
#define PHY_LED3_RCC  0X50000A28
//风扇
#define PHY_FAN_MODER 0X50006000
#define PHY_FAN_ODR  0X50006014
#define PHY_FAN_RCC 0X50000A28
//蜂鸣器
#define PHY_BUZZER_MODER 0X50003000
#define PHY_BUZZER_ODR  0X50003014
#define PHY_BUZZER_RCC 0X50000A28
//马达
#define PHY_MOTOR_MODER 0X50007000
#define PHY_MOTOR_ODR  0X50007014
#define PHY_MOTOR_RCC 0X50000A28
//功能码
#define LED_ON _IO('l',1)
#define LED_OFF _IO('l',0)
#define FAN_ON _IO('f',1)
#define FAN_OFF _IO('f',0)
#define BUZZER_ON _IO('b',1)
#define BUZZER_OFF _IO('b',0)
#define MOTOR_ON _IO('m',1)
#define MOTOR_OFF _IO('m',0)
#endif

驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include "head.h"
unsigned int *vir_led1_moder;
unsigned int *vir_led1_odr;
unsigned int *vir_led1_rcc;
unsigned int *vir_led2_moder;
unsigned int *vir_led2_odr;
unsigned int *vir_led2_rcc;
unsigned int *vir_led3_moder;
unsigned int *vir_led3_odr;
unsigned int *vir_led3_rcc;
struct cdev* cdev;
struct class* cls;
struct device* dev;
unsigned int major = 500;
unsigned int minor = 0;
dev_t devno;
char kbuf[128] = {0};// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{int a = inode->i_rdev;file->private_data = (void *)MINOR(a);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)
{long ret;if(size>sizeof(kbuf)){size = sizeof(kbuf);}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);ret = copy_to_user(ubuf, kbuf, size);if (ret){printk("copy_to_user filed\n");return -EIO;}return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{if(size>sizeof(kbuf)){size = sizeof(kbuf);}long ret;printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);ret = copy_from_user(kbuf, ubuf, size);if (ret){printk("copy_from_user filed\n");return -EIO;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mychrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{	unsigned int a;printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);a = (unsigned int)file->private_data;switch(a){case 0:if(cmd == LED_ON){*vir_led1_odr |= (0x1 << 10);}else{*vir_led1_odr &= (~(0x1 << 10));}break;case 1:if(cmd == LED_ON){*vir_led2_odr |= (0x1 << 10);}else{*vir_led2_odr &= (~(0x1 << 10));}break;case 2:if(cmd == LED_ON){*vir_led3_odr |= (0x1 << 8);}else{*vir_led3_odr &= (~(0x1 << 8));}break;}return 0;
}
//对设备文件进行操作的结构体
struct file_operations fops = {.open = mycdev_open,//打开.read = mycdev_read,//读.write = mycdev_write,//写.unlocked_ioctl = mychrdev_ioctl,//硬件功能的选择.release = mycdev_close,//关闭
};int led_init(void)
{vir_led1_moder = ioremap(PHY_LED1_MODER, 4);if (vir_led1_moder == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}vir_led1_odr = ioremap(PHY_LED1_ODR, 4);if (vir_led1_odr == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}vir_led1_rcc = ioremap(PHY_LED1_RCC, 4);if (vir_led1_rcc == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}(*vir_led1_rcc) |= (0x1 << 4);(*vir_led1_moder) &= (~(0x3 << 20));(*vir_led1_moder) |= (0x1 << 20);(*vir_led1_odr) &= (~(0x1 << 10));vir_led2_moder = ioremap(PHY_LED2_MODER, 4);if (vir_led2_moder == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}vir_led2_odr = ioremap(PHY_LED2_ODR, 4);if (vir_led2_odr == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}vir_led2_rcc = ioremap(PHY_LED2_RCC, 4);if (vir_led2_rcc == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}(*vir_led2_rcc) |= (0x1 << 5);(*vir_led2_moder) &= (~(0x3 << 20));(*vir_led2_moder) |= (0x1 << 20);(*vir_led2_odr) &= (~(0x1 << 10));vir_led3_moder = ioremap(PHY_LED3_MODER, 4);if (vir_led3_moder == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}vir_led3_odr = ioremap(PHY_LED3_ODR, 4);if (vir_led3_odr == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}vir_led3_rcc = ioremap(PHY_LED3_RCC, 4);if (vir_led3_rcc == NULL){printk("映射物理内存失败%d\n", __LINE__);return -EFAULT;}printk("映射物理内存成功\n");// 硬件寄存器的初始化(*vir_led3_rcc) |= (0x1 << 4);(*vir_led3_moder) &= (~(0x3 << 16));(*vir_led3_moder) |= (0x1 << 16);(*vir_led3_odr) &= (~(0x1 << 8));return 0;
}static int __init mycdev_init(void)
{//************分布注册驱动设备*********************int ret;//1、为驱动对象申请空间cdev = cdev_alloc();if(cdev == NULL){printk("申请空间失败\n");ret = -EFAULT;goto OUT1;}//2、对象的初始化cdev_init(cdev,&fops);//3、申请设备号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;}}//4、注册驱动对象if(cdev_add(cdev,MKDEV(major,minor),3)){printk("注册驱动对象失败\n");goto OUT3;}//************自动申请设备节点*********************//1、向上提交目录cls = class_create(THIS_MODULE, "mychrdev");if(IS_ERR(cls)){printk("向上提交目录失败\n");ret = -PTR_ERR(cls);goto OUT4;}printk("向上提交目录成功\n");// 2、向上提交设备节点信息int i;for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mychrdev%d", i);if (IS_ERR(dev)){printk("提交设备信息失败\n");ret = -PTR_ERR(dev);goto OUT5;}}printk("提交设备信息成功\n");led_init();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)
{iounmap(vir_led1_moder);iounmap(vir_led1_odr);iounmap(vir_led1_rcc);iounmap(vir_led2_moder);iounmap(vir_led2_odr);iounmap(vir_led2_rcc);iounmap(vir_led3_moder);iounmap(vir_led3_odr);iounmap(vir_led3_rcc);printk("取消映射成功\n");//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);
}
// 用于向内核报备当前内核模块入口函数的地址
module_init(mycdev_init);
// 用于向内核报备当前内核模块出口函数的地址
module_exit(mycdev_exit);
// 生命当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");

应用程序

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "head.h"
int main(int argc, char const *argv[])
{char buf[128] = {0};int led1_fd, led2_fd, led3_fd;// 打开led1设备文件led1_fd = open("/dev/mychrdev0", O_RDWR);if (led1_fd < 0){printf("打开led1设备文件失败\n");exit(-1);}// 打开led2设备文件led2_fd = open("/dev/mychrdev1", O_RDWR);if (led2_fd < 0){printf("打开led2设备文件失败\n");exit(-1);}// 打开led3设备文件led3_fd = open("/dev/mychrdev2", O_RDWR);if (led3_fd < 0){printf("打开myled3设备文件失败\n");exit(-1);}int a, b;while (1){printf("请选择要控制的器件: 1(led灯1) 2 (led灯2) 3 (led灯3) ");scanf("%d", &a);printf("请输入指令:0(关闭) 1 (打开)");scanf("%d", &b);switch (b){case 1:switch (a){case 1:ioctl(led1_fd, LED_ON);break;case 2:ioctl(led2_fd, LED_ON);break;case 3:ioctl(led3_fd, LED_ON);break;}break;case 0:switch (a){case 1:ioctl(led1_fd, LED_OFF);break;case 2:ioctl(led2_fd, LED_OFF);break;case 3:ioctl(led3_fd, LED_OFF);break;}break;}}close(led1_fd);close(led2_fd);close(led3_fd);return 0;
}

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

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

相关文章

在 3ds Max 和 After Effects 中创建逼真的蜘蛛网模型

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建蜘蛛网 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 转到创建>标准基元>平面并创建一个平面 在前视图中。 创建平面 步骤 3 保持其长度和宽度 segs 为 80。 段 步骤 4 打开修改器列表…

生活杂记-显示器尺寸

以下是常见显示器尺寸的对角线长度换算成厘米的结果&#xff08;已经四舍五入到最接近的厘米数&#xff09;&#xff1a; 19英寸显示器 ≈ 48.26厘米21.5英寸显示器 ≈ 54.61厘米24英寸显示器 ≈ 60.96厘米27英寸显示器 ≈ 68.58厘米32英寸显示器 ≈ 81.28厘米34英寸显示器 ≈…

Python爬虫之Scrapy框架系列(23)——分布式爬虫scrapy_redis浅实战【XXTop250部分爬取】

目录&#xff1a; 1.实战讲解&#xff08;XXTop250完整信息的爬取&#xff09;&#xff1a;1.1 使用之前做的完整的XXTOP250项目&#xff0c;但是设置为只爬取一页&#xff08;共25个电影&#xff09;,便于观察1.2 配置settings文件中使用scrapy_redis的必要配置&#xff0c;并…

智能汽车的主动悬架工作原理详述

摘要&#xff1a; 本文将详细介绍主动悬架功能原理设计。 主动悬架是车辆上的一种汽车悬架。它使用车载系统来控制车轮相对于底盘或车身的垂直运动&#xff0c;而不是由大弹簧提供的被动悬架&#xff0c;后者的运动完全由路面决定。主动悬架分为两类&#xff1a;真正的主动悬架…

fSGAT批量候选基因关联分析丨快速单基因关联分析

候选基因如何分析&#xff1f; 通常情况下关联分析会得到一大堆候选基因&#xff0c;总不可能每个都有用&#xff0c;因此需要对候选基因进行深一步分析&#xff0c;本篇笔记分享一下群体遗传学研究中GWAS候选位点与候选基因的筛选思路。主要的方式包括单基因关联分析、连锁程度…

ubuntu 静态IP设置

ubuntu 静态IP设置&#xff1a; 1.输入&#xff1a; sudo vim /etc/netplan/01-network-manager-all.yaml Let NetworkManager manage all devices on this system network: ethernets: ens33: dhcp4: no addresses: [192.168.1.119/24] gateway4: 192.168.1.1 nameservers: …

CASAtomic原子操作详解

一、CAS&#xff08;Compare And Swap&#xff09; 1、CAS介绍 CAS原理&#xff1a;假设有三个值&#xff0c;E&#xff08;旧值&#xff09;、U&#xff08;需要更新的值&#xff09;、V&#xff08;内存中真实的值&#xff09;&#xff0c;具体参照下图&#xff1a; 作用&a…

JavaWeb_LeadNews_Day3作业-素材管理, 文章管理

JavaWeb_LeadNews_Day3作业-素材管理, 文章管理 素材管理图片删除收藏与取消 文章管理查看文章详情文章删除文章上下架 来源 素材管理 图片删除 实现思路 检验参数, 参数为空, 返回无效参数查询图片是否存在, 不存在, 返回数据不存在查询图片是否被引用, 被引用, 返回文件使用…

[C++] C++入门第二篇 -- 引用 -- 内联函数inline -- auto+for

目录 1、引用 -- & 1.1 引用的概念 1.2 引用特性 1.3 常引用 -- 权限问题 1.4 引用的使用场景 1.4.1 做参数 1.4.2 做返回值 注意 1.5 传值、传引用的效率比较 1.6 引用和指针的区别 2、内联函数 2.1 概念 转存失败重新上传取消​编辑转存失败重新上传取消​编…

flink cdc环境搭建

1.下载flink https://archive.apache.org/dist/flink/flink-1.12.2/ 2.修改flink-conf.yaml #根据自己电脑核数修改&#xff0c;这里我设置为4&#xff0c;因为系统分配了4核 jobmanager.rpc.address: localhost #主机名根据自己设定 taskmanager.numberOfTaskSlots: 4 3.下载…

前端JS识别二维码内容

原文&#xff1a;https://www.cnblogs.com/houxianzhou/p/15030351.html <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>图片二维码识别</title><script src"https://cdn.bootcss.com/jquery/3.4.1/jque…

MATLAB实现网络相关的仿真(附上完整仿真源码)

MATLAB是一种功能强大的编程语言&#xff0c;可以用于网络相关的仿真。在本文中&#xff0c;我们将介绍如何使用MATLAB实现网络仿真&#xff0c;并附上简单的代码和完整仿真源码。 网络仿真是指通过计算机模拟网络环境&#xff0c;以评估网络性能、验证网络协议和测试网络应用…

Springboot中 AOP实现日志信息的记录到数据库

1、导入相关的依赖 <!--spring切面aop依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency> 注意&#xff1a;在application.properties文件里加这样一…

【前端设计】使用Verdi查看波形时鼠标遮住了parameter值怎么整

盆友&#xff0c;你们在使用Verdi的时候&#xff0c;有没有遇到过鼠标遮挡着了parameter数值的场景&#xff1f;就跟下面这个示意图一样&#xff1a; 最可恨的是这个参数值他会跟着你的鼠标走&#xff0c;你想把鼠标移开看看看这个例化值到底是多大吧&#xff0c;这个数他跟着你…

Python实现人脸识别功能

Python实现人脸识别功能 闲来没事&#xff0c;记录一下前几天学习的人脸识别小项目。 要想实现人脸识别&#xff0c;我们首先要搞明白&#xff0c;人脸识别主要分为哪些步骤&#xff1f;为了提高人脸识别的准确性&#xff0c;我们首先要把图像或视频中的人脸检测出来&#xf…

基于DNN深度学习网络的OFDM+QPSK信号检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................................. Transmitt…

XGBoost实例——皮马印第安人糖尿病预测和特征筛选

利用皮马印第安人糖尿病数据集来预测皮马印第安人的糖尿病&#xff0c;以下是数据集的信息&#xff1a; Pregnancies&#xff1a;怀孕次数Glucose&#xff1a;葡萄糖BloodPressure&#xff1a;血压 (mm Hg)SkinThickness&#xff1a;皮层厚度 (mm)Insulin&#xff1a;胰岛素 2…

区块链学习笔记

区块链技术与应用 数组 列表 二叉树 哈希函数 BTC中的密码学原理 cryptographic hash function collsion resistance(碰撞抵抗) 碰撞指的是找到两个不同的输入值&#xff0c;使得它们的哈希值相同。也就是说&#xff0c;如果存在任意两个输入x和y&#xff0c;满足x ≠ y…

【N32L40X】学习笔记03-gpio输出库

gpio输出 该函数库的目的就是在统一的地方配置&#xff0c;将配置的不同项放置在一个结构体内部使用一个枚举来定义一个的别名 led.c #include <stdio.h> #include "led/bsp_led.h"static led_t leds[LED_NUM]{{GPIOB,GPIO_PIN_2,RCC_APB2_PERIPH_GPIOB},{GP…

Android获取屏幕的宽高、密度等

转载他人的链接 Android 获取屏幕尺寸与密度获取屏幕密度&#xff08;方法1&#xff09; int screenWidth getWindowManager().getDefaultDisplay().getWidth(); // 屏幕宽&#xff08;像素&#xff0c;如&#xff1a;480px&#xff09; int screenHeight getWin…