day4驱动开发

目的:通过字符设备驱动的分步实现编写LED驱动,另外实现特备文件和设备的绑定

驱动文件 :

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/io.h>
#include "head.h"struct cdev *cdev;
unsigned int major = 0;
unsigned int minor = 0;
struct class *cls;
struct device *dev;gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;int mycdev_open (struct inode * inode, struct file * file)
{printk("%s : %s : %d\n",__FILE__,__func__,__LINE__);int min = MINOR(inode->i_rdev);file->private_data = (void *)min;return 0;
}long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{printk("%s : %s : %d\n",__FILE__,__func__,__LINE__);int which = (int)file->private_data;printk("which = %d\n",which);switch(cmd){case LED_ON:switch(which){case 0://LED1vir_led1->ODR |= (0x1 << 10);break;case 1://LED2vir_led2->ODR |= (0x1 << 10);break;case 2://LED3vir_led3->ODR |= (0x1 << 8);break;}break;{case LED_OFF:switch(which){case 0://LED1vir_led1->ODR &= (~(0x1 << 10));break;case 1://LED2vir_led2->ODR &= (~(0x1 << 10));break;case 2://LED3vir_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,
};static int __init mycdev_init(void)
{//寄存器地址的映射vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));if(vir_led1==NULL){printk("ioremap filed:%d\n",__LINE__);return -ENOMEM;}vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));if(vir_led2==NULL){printk("ioremap filed:%d\n",__LINE__);return -ENOMEM;}vir_led3=vir_led1;vir_rcc=ioremap(PHY_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_led3->MODER |= (1<<16);vir_led3->ODR &= (~(1<<8));printk("寄存器初始化成功\n");int ret;//申请一个对象空间cdev = cdev_alloc();if(cdev == NULL){printk("cdev_alloc failed\n");ret = -EFAULT;goto out1;}printk("cdev_alloc success\n");//初始化对象cdev_init(cdev,&fops);//申请设备号if(major == 0)//动态申请{dev_t devnu;ret = alloc_chrdev_region(&devnu,minor,3,"mydev");if(ret){printk("alloc_chrdev_region failed\n");goto out2;}major = MAJOR(devnu);minor = MINOR(devnu);printk("alloc_chrdev_region success\n");}else//静态申请{ret = register_chrdev_region(major,3,"mydev");if(ret){printk("register_chrdev_region failed\n");goto out2;}printk("register_chrdev_region success\n");}//注册驱动对象ret = cdev_add(cdev,MKDEV(major,minor),3);if(ret){printk("cdev_add failed\n");goto out3;}printk("cdev_add success\n");//向上提交目录cls = class_create(THIS_MODULE,"mychrdev");if(IS_ERR(cls)){printk("class_create failed\n");goto out4;}printk("class_create success\n");//向上提交节点信息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("device_create failed\n");goto out5;}}printk("device_create success\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)
{//销毁设备节点信息int i;for(i=0;i<3;i++){device_destroy(cls,MKDEV(major,i));}//销毁目录class_destroy(cls);//销毁字符设备驱动对象cdev_del(cdev);//释放设备号unregister_chrdev_region(MKDEV(major,minor),3);//释放申请到的字符设备驱动对象空间kfree(cdev);}module_init(mycdev_init);
module_exit(mycdev_exit);
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 fd1 = open("/dev/mychrdev0", O_RDWR);if (fd1 < 0){printf("打开设备文件失败\n");exit(-1);}// 打开第二个设备文件int fd2 = open("/dev/mychrdev1", O_RDWR);if (fd2 < 0){printf("打开设备文件失败\n");exit(-1);}// 打开第三个设备文件int fd3 = open("/dev/mychrdev2", O_RDWR);if (fd3 < 0){printf("打开设备文件失败\n");exit(-1);}while (1){int a, b;// 从终端读取printf("请输入字符\n");printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");scanf("%d", &a);printf("第二个字符:0(关灯) 1(开灯)\n");printf("请输入>");scanf("%d", &b);// 向设备文件中写switch (b){case 1:switch (a){case 1: // LED1ioctl(fd1, LED_ON);break;case 2: // LED2ioctl(fd2, LED_ON);break;case 3: // LED3ioctl(fd3, LED_ON);break;}break;case 0:switch (a){case 1: // LED1ioctl(fd1, LED_OFF);break;case 2: // LED2ioctl(fd2, LED_OFF);break;case 3: // LED3ioctl(fd3, LED_OFF);break;}break;}}close(fd1);close(fd2);close(fd3);return 0;
}

头文件 :

#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;#define PHY_LED1_ADDR 0X50006000
#define PHY_LED2_ADDR    0X50007000
#define PHY_LED3_ADDR 0X50006000
#define PHY_RCC_ADDR    0X50000A28#define LED_ON _IO('l',1)
#define LED_OFF _IO('l',0)#endif 

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

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

相关文章

day40

今日内容概要 针对记录的SQL语句 配置文件的介绍 存储引擎的使用(存储的方式) 数据类型(重点) 整型 浮点型 字符串 日期 枚举 针对记录的sql语句 针对库的增删改查&#xff08;文件夹&#xff09; 1.创建库 create databases db1; # 设置库的默认编码 create databa…

illuminate/database 使用 一

illuminate/database 是完整的php数据库工具包&#xff0c;即ORM&#xff08;Object-Relational Mapping&#xff09;类库。 提供丰富的查询构造器&#xff0c;和多个驱动的服务。作为Laravel的数据库层使用&#xff0c;也可以单独使用。 一 使用 加载composer之后&#xff…

自然语言处理---迁移学习

fasttext介绍 作为NLP工程领域常用的工具包&#xff0c;fasttext有两大作用&#xff1a;进行文本分类、训练词向量。在保持较高精度的情况下&#xff0c;快速的进行训练和预测是fasttext的最大优势。fasttext优势的原因: fasttext工具包中内含的fasttext模型具有十分简单的网络…

01-React入门

React概述 react是什么&#xff1f; React用于构建用户界面的JS库。是一个将数据渲染为HTML视图的开源JS库。 为什么学&#xff1f; 1.原生JS操作DOM繁琐&#xff0c;效率低 2.使用JS直接操作DOM,浏览器会进行大量的重绘重排 3.原生JS没有组件化编码方案&#xff0c;代码…

2024 王道考研-数据结构

第二章 线性表算法题(线性表的顺序表示) 二、综合应用题 01.从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位 置由最后一个元素填补&#xff0c;若顺序表为空&#xff0c;则显示出错信息并退出运行。 算法思想&#xff1a;搜索整个顺序表&#xf…

Python之PyMySQL操作详解

一、PyMysql简介 PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库&#xff0c;Python2中则使用mysqldb。 Django中也可以使用PyMySQL连接MySQL数据库。 二、PyMySQL操作详解 2.1 PyMySQL安装 pip install pymysql2.2 PyMySQL应用 2.2.1 基本使用 # codingut…

【Leetcode】 213. 打家劫舍 II ?

你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈&#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚…

sql server2014如何添加多个实例 | 以及如何删除多个实例中的单个实例

标题sql server2014如何添加多个实例 前提&#xff08;已安装sql server2014 且已有默认实例MSSQLSERVER&#xff09; 添加新的实例 其实就是根据安装步骤再安装一次&#xff08;区别在过程中说明&#xff09; 双击安装 选择“全新独立安装或添加现有功能” 然后下一步下一…

Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)

介绍 Apache Shiro是一款开源安全框架&#xff0c;提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用&#xff0c;同时也能提供健壮的安全性。 版本 Apache Shiro 1.2.4及以前版本中 原理 不安全的配置 默认账户在里面 Apache Shiro 1.2.4及以前版本中&#x…

C++学习之强制类型转换

强制类型转换运算符 带着三个疑问阅读&#xff1a; 出现的背景是什么&#xff1f;何时使用&#xff1f;如何使用&#xff1f; MSDN . 强制转换运算符 C中的四种强制类型转换符详解 static_cast (1) 使用场景 在基本数据类型之间转换&#xff0c;如把 int 转换为 char&#…

pkg-config使用

作用&#xff1a;pkg-config是linux中的应用程序&#xff0c;可以方便导入第三方模块的头文件和库文件。很多模块是支持pkg-config的&#xff0c;这些模块&#xff08;如dpdk&#xff09;在编译安装后会生成**.pc**后缀的文件&#xff0c;pkg-config通过pc文件可以知道模块的头…

Python 数组和列表:创建、访问、添加和删除数组元素

Python 没有内置支持数组&#xff0c;但可以使用 Python 列表来代替。 数组 本页将向您展示如何使用列表作为数组&#xff0c;但要在 Python 中使用数组&#xff0c;您需要导入一个库&#xff0c;比如 NumPy 库。数组用于在一个变量中存储多个值&#xff1a; 示例&#xff0…

大数据学习(17)-mapreduce task详解

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

重生奇迹mu宠物带来不一样的体验

重生奇迹mu宠物有什么作用&#xff1f; 全新版本中更是推出了各种宠物&#xff0c;在玩游戏时还可以带着宠物&#xff0c;一起疯狂的刷怪等等&#xff0c;可以为玩家带来非常不错的游戏体验&#xff0c;那么下面就来给大家说说各种宠物适合做什么事情。 1、强化恶魔适合刷怪 …

java头歌-java中的异常

文章目录 第一关第二关第三关第四关 第一关 第二关 题目要求&#xff1a; public static void main(String[] args) {Scanner sc new Scanner(System.in);try {int num1 sc.nextInt();int num2 sc.nextInt();/********* Begin *********/System.out.println(num1/num2);}…

【SA8295P 源码分析 (四)】21 - Android GVM 虚拟网络 vlan 配置

【SA8295P 源码分析】21 - Android GVM 虚拟网络 vlan 配置 一、Android GVM 虚拟网络 vlan 配置二、网络验证三、网桥配置:让 Android GVM 可以通过 emac 访问外网四、兼容前后排车机:使用 QNX 环境变量进行区分五、动态修改 mac 地址六、VLAN原理系列文章汇总见:《【SA829…

Redis | 在Java中操作Redis

在Java中操作Redis&#xff1a; 第一步: pom.xml文件中导入maven依赖第二步: 在application.yml配置文件中 配置Redis数据源第三步: 编写RedisConfiguration配置类&#xff0c;创建RedisTemplate对象第四步: 通过RedisTemplate对象操作Redis / Redis中的数据4.1 操作“字符串St…

CNN——卷积神经网络

文章目录 多层感知机&#xff08;MLP&#xff0c;Multilayer Perceptron&#xff09;神经网络定义MLP与神经网络的异同相同之处&#xff1a;不同之处&#xff1a;总结 为什么要使用神经网络CNN卷积层&#xff1a;池化层&#xff1a;全连接层&#xff1a; 卷积神经网络的优势pad…

Python---while循环的执行流程 解释

使用Debug调试工具&#xff0c;查看while循环的运行流程 代码 # ① 初始化计数器 i 1 # ② 编写循环条件&#xff08;判断计数器是否达到了100&#xff09; while i < 100:print(f{i 1}、老婆大人&#xff0c;我错了)# ③ 在循环体内部更新计数器i 1 ① 代码都是顺序执行…