当前位置: 首页 > 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系列命…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

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

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

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...