【驱动开发day4作业】

头文件代码

#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 _IOW('l',1,int)
#define LED_OFF _IOW('l',0,int)#endif 

 应用层代码

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include "head.h"int main(int argc, char const *argv[])
{char buf[128] = {0};int a, b;int fd;while (1){// 从终端读取printf("请输入要打开哪个设备>");printf("0:LED1 1:LED2 2:LED3\n");printf("请输入>");scanf("%d", &b);if (b == 0){fd = open("/dev/mycdev0", O_RDWR);}else if (b == 1){fd = open("/dev/mycdev1", O_RDWR);}else if (b == 2){fd = open("/dev/mycdev2", O_RDWR);}if (fd < 0){printf("打开设备文件失败\n");exit(-1);}printf("请输入指令\n");printf("0(关灯) 1(开灯)\n");printf("请输入>");scanf("%d", &a);switch (a){case 1:ioctl(fd, LED_ON); // 开灯break;case 0:ioctl(fd, LED_OFF);break;}close(fd);}return 0;
}

 驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include<linux/slab.h>
#include<linux/cdev.h>
#include "head.h"dev_t devid;
struct cdev *cdev;
unsigned int major = 500;
unsigned int minor = 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 which_dev = inode->i_rdev;//将次设备号保存到当前文件的file结构中file->private_data = (void *)MINOR(which_dev);printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{unsigned int which_dev = (unsigned int)file->private_data; switch(which_dev){case 0://LED1控制逻辑;if(cmd == LED_ON){vir_led1->ODR |= (0x1 << 10); // LED1开灯}else if(cmd == LED_OFF){vir_led1->ODR &= (~(0X1 << 10));}break;   case 1://LED2控制逻辑;if(cmd == LED_ON){vir_led2->ODR |= (0x1 << 10); // LED2开灯}else if(cmd == LED_OFF){vir_led2->ODR &= (~(0X1 << 10));}break; case 2://LED3控制逻辑;if(cmd == LED_ON){vir_led3->ODR |= (0x1 << 8); // LED3开灯}else if(cmd == LED_OFF){vir_led3->ODR &= (~(0X1 << 8));}break;                          }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__);return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);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,.read = mycdev_read,.write = mycdev_write,
};// 灯的寄存器映射以及初始化
int all_led_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_led1->MODER |= (1 << 16);vir_led1->ODR &= (~(1 << 8));printk("灯的寄存器初始化成功\n");return 0;
}static int __init mycdev_init(void)
{int ret;// 1.申请对象空间 cdev_alloccdev = 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(&devid, minor, 3, "mycdev");if (ret != 0){printk("动态申请设备号失败\n");goto OUT2;}//统一后面的操作major = MAJOR(devid); //根据设备号获取主设备号minor = MINOR(devid);}//静态指定申请else{ret = register_chrdev_region(MKDEV(major,minor),3,"mycdev");if(ret != 0){printk("静态指定设备号失败\n");goto OUT2;}}printk("申请设备号成功\n");// 4.注册驱动对象 cdev_add()ret = cdev_add(cdev, MKDEV(major,minor), 3);if (ret != 0){printk("注册设备驱动对象失败\n");goto OUT3;}printk("注册设备驱动对象成功\n");// 5.向上提交目录  class_create()cls = class_create(THIS_MODULE, "mycdev");if (IS_ERR(cls)){printk("向上提交目录失败\n");goto OUT4;}printk("向上提交目录成功\n");// 6.向上提交设备信息 device_create()int 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");// 灯的寄存器映射以及初始化all_led_init();return 0;
OUT5:
//将提交成功的设备信息销毁
for(--i;i>=0;i--)
{device_destroy(cls,MKDEV(major,i));
}
OUT4:class_destroy(cls);
OUT3:unregister_chrdev_region(MKDEV(major,minor), 3);
OUT2:kfree(cdev);
OUT1:return ret;
}static void __exit mycdev_exit(void)
{// 取消地址映射iounmap(vir_led1);iounmap(vir_led2);iounmap(vir_rcc);// 1.销毁设备信息  device_destroyint i;for(i=0;i<3;i++){device_destroy(cls,MKDEV(major,i));}// 2.销毁目录    class_destroyclass_destroy(cls);// 3.注销驱动对象  cdev_delcdev_del(cdev);// 4.释放设备号   unregister_chrdev_region()unregister_chrdev_region(MKDEV(major,minor),3);// 5.释放对象空间   kfree()kfree(cdev);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

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

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

相关文章

数据库数据恢复-Syabse数据库存储页底层数据杂乱的数据恢复案例

数据库恢复环境&#xff1a; Sybase版本&#xff1a;SQL Anywhere 8.0。 数据库故障&#xff1a; 数据库所在的设备意外断电后&#xff0c;数据库无法启动。 错误提示&#xff1a; 使用Sybase Central连接后报错&#xff1a; 数据库故障分析&#xff1a; 经过北亚企安数据恢复…

Android 面试题 应用程序结构 九

&#x1f525; 核心应用程序 Activity五个状态&#x1f525; Starting-> running-> paused-> stopped-> killed 启动状态&#xff08;Starting&#xff09;&#xff1a;Activity的启动状态很短暂&#xff0c;当Activity启动后便会进入运行状态&#xff08;Running…

数据库架构演变过程

&#x1f680; ShardingSphere &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&…

【JavaEE】博客系统前后端交互

目录 一、准备工作 二、数据库的表设计 三、封装JDBC数据库操作 1、创建数据表对应的实体类 2、封装增删改查操作 四、前后端交互逻辑的实现 1、博客列表页 1.1、展示博客列表 1.2、博客详情页 1.3、登录页面 1.4、强制要求用户登录&#xff0c;检查用户的登录状态 …

浏览器访问nginx转发打开oss上的html页面默认是下载,修改为预览

使用阿里云盒OSS上传了html页面&#xff0c;在nginx里配置跳转访问该页面时&#xff0c;在浏览器里直接默认下载了该页面&#xff0c;现在想实现预览功能&#xff0c;只需在nginx里的location里修改消息头的Content-Disposition为inline即可 注意要隐藏头信息proxy_hide_header…

万年历【小游戏】(Java课设)

系统类型 Java实现的小游戏 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Idea或eclipse 运行效果 更多Java课设系统源码地址&#xff1a;更多Java课设系统源码地址 更多Java小游戏运行效果展示&#xff1a;更多Java小游戏运行效果展…

pytest——断言后继续执行

前言 在编写测试用例的时候&#xff0c;一条用例可能会有多条断言结果&#xff0c;当然在自动化测试用例中也会遇到这种问题&#xff0c;我们普通的断言结果一旦失败后&#xff0c;就会出现报错&#xff0c;哪么如何进行多个断言呢&#xff1f;pytest-assume这个pytest的插件就…

TiProxy 原理和实现

说明 在上篇《TiProxy 尝鲜》 中做了一些实验&#xff0c;比如加减tidb节点后tiproxy可以做到自动负载均衡&#xff0c;如果遇到会话有未提交的事务则等待事务结束才迁移。 本次主要研究这样的功能在tiproxy中是如何实现的&#xff0c;本次分享内容主要为以下几部分&#xff…

【 Python 全栈开发 - 人工智能篇 - 45 】决策树与随机森林

文章目录 一、概念与原理1.1 决策树1.1.1 概念1.1.2 原理特征选择分割方法 1.1.3 优点与缺点1.1.4 Python常用决策树算法 1.2 随机森林1.2.1 概念1.2.2 原理1.2.3 优点与缺点1.2.4 Python常用随机森林算法 1.3 决策树与随机森林的比较1.3.1 相同之处1.3.2 不同之处 二、决策树算…

嵌入式开发:单片机嵌入式Linux学习路径

SOC&#xff08;System on a Chip&#xff09;的本质区别在于架构和功能。低端SOC如基于Cortex-M架构的芯片&#xff0c;如STM32和NXP LPC1xxx系列&#xff0c;不具备MMU&#xff08;Memory Management Unit&#xff09;&#xff0c;适用于轻量级实时操作系统如uCOS和FreeRTOS。…

Vue基础-综合案例(基于vue2)

一、目标 能够知道如何使用vue-cli创建vue项目能够知道如何在项目中安装与配置element-ui能够知道element-ui中常见组件的用法能够知道如何使用axios中的拦截器能够知道如何配置proxy接口代理 二、目录 vue-cli组件库axios拦截器proxy跨域代理用户列表案例 vue-cli 1.什么…

利用mysqldump实现分库分表备份的shell脚本

一、信息摘要 linux版本&#xff1a;CentOS 7.9 mysql版本&#xff1a;MySQL 5.7.36 脚本实现功能&#xff1a;利用mysqldump工具实现对mysql中的数据库分库备份&#xff0c;和对所备份数据库中的表分表备份 二、shell脚本 #!/bin/bash ######################### #File n…

[Linux]进程控制详解!!(创建、终止、等待、替换)

hello&#xff0c;大家好&#xff0c;这里是bang___bang_&#xff0c;在上两篇中我们讲解了进程的概念、状态和进程地址空间&#xff0c;本篇讲解进程的控制&#xff01;&#xff01;包含内容有进程创建、进程等待、进程替换、进程终止&#xff01;&#xff01; 附上前2篇文章…

使用Beego和MySQL实现帖子和评论的应用,并进行接口测试(附源码和代码深度剖析)

文章目录 小项目介绍源码分析main.gorouter.gomodels/user.gomodels/Post.gomodels/comment.gocontrollers/post.gocontrollers/comment.go 接口测试测试增加帖子测试查看帖子测试增加评论测试查看评论 小项目介绍 经过对需求的分析&#xff0c;我增加了一些额外的东西&#x…

Open3D (C++) ISS特征点提取

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫网站自重,把自己当个人 一、算法原理 1、原理概述 内部形状描述子(ISS)是一种表示立体几何形状的方法,该算法含有丰富的几何特征信息,可以完成高质量的点云配准。设…

禁用右键菜单AMD Software: Adrenalin Edition

本文参考链接&#xff1a; 删除win11右键一级菜单的AMD驱动栏 - 哔哩哔哩 windows11 求助删除右键菜单方法_windows11吧_百度贴吧 Windows安装最新的AMD显卡驱动后&#xff0c;右键菜单会多出AMD Software: Adrenalin Edition。使用一些右键菜单管理工具也没能屏蔽禁用掉该功…

mybatis-config.xml-配置文件详解

文章目录 mybatis-config.xml-配置文件详解说明文档地址:配置文件属性解析properties 属性应用实例 settings 全局参数定义应用实例 typeAliases 别名处理器举例说明 typeHandlers 类型处理器environments 环境environment 属性应用实例 mappers配置 mybatis-config.xml-配置文…

运维高级--shell脚本完成分库分表

为什么要进行分库分表 随着系统的运行&#xff0c;存储的数据量会越来越大&#xff0c;系统的访问的压力也会随之增大&#xff0c;如果一个库中的表数据超过了一定的数量&#xff0c;比如说MySQL中的表数据达到千万级别&#xff0c;就需要考虑进行分库分表&#xff1b; 其…

iOS-持久化

目的 1.快速展示&#xff0c;提升体验 已经加载过的数据&#xff0c;用户下次查看时&#xff0c;不需要再次从网络&#xff08;磁盘&#xff09;加载&#xff0c;直接展示给用户 2.节省用户流量&#xff08;节省服务器资源&#xff09; 对于较大的资源数据进行缓存&#xf…

ClickHouse(六):Clickhouse数据类型-1

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…