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

驱动day4作业

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

head.h

#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 

demo1.c

#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"char kbuf[128]={0};
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;
struct cdev *cdev;
dev_t devno;
unsigned int major=0;
unsigned int minor=0;
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:switch (cmd){case LED_ON:vir_led1->ODR |= (0x1 << 10);break;case LED_OFF:vir_led1->ODR &= (~(0X1 << 10));break;}break;case 1:switch (cmd){case LED_ON:vir_led2->ODR |= (0X1 << 10);break;case LED_OFF:vir_led2->ODR &= (~(0X1 << 10));break;}break;case 2:switch (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(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;cdev=cdev_alloc();if(cdev == NULL){printk("申请对象失败\n");ret=-EFAULT;goto out1;}printk("申请对象成功\n");cdev_init(cdev,&fops);if(major == 0){ret = alloc_chrdev_region(&devno,minor,3,"mychrdev");if(ret){printk("申请设备号失败\n");goto out2;}printk("申请设备号成功\n");major=MAJOR(devno);minor=MINOR(devno);}ret=cdev_add(cdev,MKDEV(major,minor),3);if(ret){printk("注册对象失败\n");goto out3;}printk("注册对象成功\n");cls=class_create(THIS_MODULE,"mychrdev");if(IS_ERR(cls)){printk("向上提交目录失败\n");goto out4;}printk("向上提交目录成功\n");int i;for(i=0;i<3;i++){dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%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));}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);iounmap(vir_led2);iounmap(vir_rcc);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");

text.c

#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include<unistd.h>
#include<string.h>
#include "head.h"int main(int argc, char const *argv[])
{int fd;char name[20]={0};int a,b;while(1){printf("请选择要控制的灯:1(LED1)2(LED2) 3(LED3)\n");printf("请输入>");scanf("%d",&b);switch(b){case 1:strcpy(name,"/dev/myled0");break;case 2:strcpy(name,"/dev/myled1");break;case 3:strcpy(name,"/dev/myled2");break;}fd=open(name,O_RDWR);if(fd<0){printf("打开设备文件失败\n");exit(-1);}//从终端读取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;
}

相关文章:

驱动day4作业

通过字符设备驱动的分步实现编写LED驱动&#xff0c;另外实现特备文件和设备的绑定 head.h #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; }…...

【Oracle】VC6.0使用 odbc 访问 Oracle 存储过程

环境说明 系统环境 系统&#xff1a;Windows XP IDE&#xff1a; Microsoft Visual C 6.0 使用的对象 msado15.tlh _ConnectionPtr m_pConnection; HRESULT hr m_pConnection.CreateInstance(“ADODB.Connection”); _RecordsetPtr m_pRecordset; m_pRecordset.CreateInstan…...

QWidget快速美化-圆形蓝色单选框

将代码复制进QRadioButton的样式表 效果: 代码: QRadioButton{font:75 9pt "Arial";background:transparent;color:white;border:none; }QRadioButton:disabled{color:gray; }QRadioButton::indicator{width:12px;height:12px;border-radius:8px; }QRadioButton::i…...

adb 获取当前界面元素

adb配置正确&#xff0c;直接看6&#xff0c;pull的位置是你执行pull的目录下。 --------------------------------------------------------------------------------------------------------------------------------- 使用adb命令获取当前应用的元素需要先连接到手机或模…...

SpringSecurity源码学习四:会话管理

目录 1. 什么是会话管理2. springSecurity中的session管理怎么做的3. springSecurity源码中的session管理4. 代码示例5. 源码5.1 不同策略的含义 6. 集群模式session管理7. 总结 1. 什么是会话管理 会话管理是指在Java应用程序中管理用户会话状态的过程。在Spring框架中&#…...

Kotlin笔记(七):协程

1. 协程的定义 协程属于Kotlin中非常有特色的一项技术&#xff0c;因为大部分编程语言中是没有协程这个概念的。 什么是协程呢&#xff1f;它其实和线程是有点类似的&#xff0c;可以简单地将它理解成一种轻量级的线程。要知道&#xff0c;线程是非常重量级的&#xff0c;它需要…...

存储优化知识复习二详细版解析

存储优化 知识复习二 一、 选择题 1、 对数据库调优的方法中&#xff0c;最困难但是最有成效的是( )。 A、优化表的架构设计 B、添加内存 C、索引优化 D、查询语句优化 【参考答案】A2、 防止与处理死锁的方法有&#xff08; &#xff09;。 A、尽量避免或尽快处理阻塞 B、访…...

《持续交付:发布可靠软件的系统方法》- 读书笔记(七)

持续交付&#xff1a;发布可靠软件的系统方法&#xff08;七&#xff09; 第 7 章 提交阶段7.1 引言7.2 提交阶段的原则和实践7.2.1 提供快速有用的反馈7.2.2 何时令提交阶段失败7.2.3 精心对待提交阶段7.2.4 让开发人员也拥有所有权7.2.5 在超大项目团队中指定一个构建负责人 …...

Go源码实现使用多线程并发下载大文件的功能

摘要&#xff1a;Go语言编码实现了使用多线程并发下载文件的功能。 1. 代码流程介绍 1. 获取系统的CPU核心数量&#xff0c;并将其作为线程数的参考值&#xff0c;并打印出来。 2. 定义要下载的文件的URL、线程数和输出文件名。 3. 使用getFileSize()函数获取文件大小&#xf…...

Python基础入门例程1-NP1 Hello World!

描述 将字符串 Hello World! 存储到变量str中&#xff0c;再使用print语句将其打印出来。 输入描述&#xff1a; 无 输出描述&#xff1a; 一行输出字符串Hello World! 解答&#xff1a; str "Hello World!" print(str) 解释说明&#xff1a; 赋值变量&…...

前端面试题10.23

解决的最复杂的前端问题&#xff0c;介绍一下 最复杂的前端问题之一是浏览器兼容性&#xff0c;不同浏览器对网页的渲染方式存在差异&#xff0c;需要针对不同浏览器做兼容性处理。此外&#xff0c;前端性能优化也是一个复杂的问题&#xff0c;需要综合考虑网页加载速度、渲染…...

DYC算法开发与测试(基于ModelBase实现)

ModelBase是经纬恒润开发的车辆仿真软件&#xff0c;包含两个大版本&#xff1a;动力学版本、智能驾驶版本。动力学版包含高精度动力学模型&#xff0c;能很好地复现车辆在实际道路中运行的各种状态变化&#xff0c;可用于乘用车、商用车动力底盘系统算法开发、控制器仿真测试&…...

第四章 路由基础

目录 4.1 路由器概述 4.1.1 路由器定义 4.1.2 路由器工作原理 4.1.3 路由表的生成方式 &#xff08;1&#xff09;直连路由 &#xff08;2&#xff09;静态路由 &#xff08;3&#xff09;动态路由 4.1.4 路由器的接口 &#xff08;1&#xff09;配置接口 &#xff0…...

Java逻辑运算符(、||和!),Java关系运算符

逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式&#xff0c;以判断程序中的表达式是否成立&#xff0c;判断的结果是 true 或 false。 逻辑运算符是对布尔型变量进行运算&#xff0c;其结果也是布尔型&#xff0c;具体如表 1 所示。 表 1 逻辑运算符的用…...

三个设备文件

...

Java赋值运算符(=)

赋值运算符是指为变量或常量指定数值的符号。赋值运算符的符号为“”&#xff0c;它是双目运算符&#xff0c;左边的操作数必须是变量&#xff0c;不能是常量或表达式。 其语法格式如下所示&#xff1a; 变量名称表达式内容 在 Java 语言中&#xff0c;“变量名称”和“表达式…...

提升药店效率:山海鲸医药零售大屏的成功案例

在医药行业中&#xff0c;特别是医药零售领域&#xff0c;高效的药品管理和客户服务至关重要。随着科技的飞速发展&#xff0c;数字化解决方案已经成为提高医药零售管控效率的有效工具之一。其中&#xff0c;医药零售管控大屏作为一种强大的工具&#xff0c;正在以独特的方式改…...

使用Fragement(碎片)

一、Fragment简介 屏幕大小的差距可能会使同样的界面在不同设备上显示出不同的效果&#xff0c;为了能同时兼顾到手机和平板电脑的开发&#xff0c;从Android3.0版本开始提供了Fragment。 Fragment&#xff08;碎片&#xff09;是一种嵌入在Activity中的UI片段&#xff0c;它…...

种花问题(Python题目)

假设有一个很长的花坛&#xff0c;一部分地块种植了花&#xff0c;另一部分却没有。可是&#xff0c;花不能种植在相邻的地块上&#xff0c;它们会争夺水源&#xff0c;两者都会死去。 给你一个整数数组 flowerbed 表示花坛&#xff0c;由若干 0 和 1 组成&#xff0c;其中 0 …...

STM32入门F4

学习资料&#xff1a;杨桃电子&#xff0c;官网&#xff1a;洋桃电子 | 杜洋工作室 www.doyoung.net 嵌入式开发核心宗旨&#xff1a;以最适合的性能、功能、成本来完成最有性价比的产品开发。 1.为什么要学F407 STM32F103系列与STM32F407系列对照表&#xff1a; 2.F4系列命…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

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

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

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...