驱动实现LED点灯

demo.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "head.h"
//定义三个指针指向映射后的虚拟内存
unsigned int *vir_moder;
unsigned int *vir_odr;
unsigned int *vir_led2_moder;
unsigned int *vir_led2_odr;
unsigned int *vir_rcc;
unsigned int major;
char kbuf[128]={};
//封装操作方法
int mycdev_open(struct inode *inode,struct file *file)
{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)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);int ret;//将内核空间数据拷贝到用户空间ret=copy_to_user(ubuf,kbuf,size);if(ret){printk("copy_to_user failed!\n");return -EIO;}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__);int ret;//从用户空间拷贝数据到内核空间ret=copy_from_user(kbuf,ubuf,size);if(ret){printk("copy_from_user failed!\n");return -EIO;}printk("kbuf=%s\n",kbuf);//led1if(kbuf[0] == '0')//关灯{printk("kbuf[0]=%c\n",kbuf[0]);//关灯逻辑(*vir_odr) &= (~(0x1<<10));}if(kbuf[0] == '1')//开灯{//开灯逻辑(*vir_odr) |= (0x1<<10);}//led2if(kbuf[1] == '0')//关灯{//关灯逻辑(*vir_led2_odr) &= (~(0x1<<10));}if(kbuf[1] == '1')//开灯{printk("kbuf[1]=%c\n",kbuf[1]);//开灯逻辑(*vir_led2_odr) |= (0x1<<10);}//led3if(kbuf[2] == '0')//关灯{//关灯逻辑(*vir_odr) &= (~(0x1<<8));}if(kbuf[2] == '1')//开灯{printk("kbuf[2]=%c\n",kbuf[2]);//开灯逻辑(*vir_odr) |= (0x1<<8);}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,.read=mycdev_read,.write=mycdev_write,.release=mycdev_close,
};
//入口函数
static int __init mycdev_init(void)
{major = register_chrdev(0,"mychrdev",&fops);if(major < 0){printk("字符设备驱动注册失败\n");return major;}printk("注册字符设备驱动成功major=%d\n",major);//进行寄存器地址的映射vir_moder = ioremap(PHY_LED1_3_MODER,4);if(vir_moder == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}vir_odr = ioremap(PHY_LED1_3_ODR,4);if(vir_odr == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}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_rcc = ioremap(PHY_RCC,4);if(vir_rcc == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}printk("物理内存映射成功\n");//LED寄存器初始化(*vir_rcc) |= (0x3 << 4);//GPIOE和GPIOF控制器使能(*vir_moder) &= (~(0x3 << 20));//MODER[21:20]->00(*vir_moder) &= (~(0x3 << 16));//MODER[17:16]->00(*vir_moder) |= (0x1 << 20);//MODER[21:20]->01 PE10(*vir_moder) |= (0x1 << 16);//MODER[17:16]->01 PE8(*vir_led2_moder) &= (~(0x3 << 20));//MODER[21:20]->00(*vir_led2_moder) |= (0x1 << 20);//MODER[21:20]->01 PF10(*vir_odr) &= (~(0x1 << 10));(*vir_odr) &= (~(0x1 << 8));(*vir_led2_odr) &= (~(0x1 << 10));return 0;
}//出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{//#define __exit     __section(".exit.text")//__exit指定出口函数保存在。exit.text段中//取消映射内存iounmap(vir_moder);iounmap(vir_odr);iounmap(vir_led2_moder);iounmap(vir_led2_odr);iounmap(vir_rcc);//注销字符设备驱动unregister_chrdev(major,"mychrdev");}//用于声明入口函数
module_init(mycdev_init);
//用于声明出口函数
module_exit(mycdev_exit);
//声明当前内核模块遵循GPL协议(许可证)
MODULE_LICENSE("GPL");

head.h

#ifndef __HEAD_H__
#define __HEAD_H__
#define PHY_LED2_MODER 0x50007000
#define PHY_LED2_ODR 0x50007014
#define PHY_LED1_3_MODER 0x50006000
#define PHY_LED1_3_ODR 0x50006014
#define PHY_RCC 0x50000A28#endif

text.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{char buf[128] = {0};int fd = open("/dev/mychrdev",O_RDWR);if(fd < 0){printf("打开设备文件失败\n");return -1;}printf("打开设备文件册成功\n");while(1){printf("请输入要进行的操作(三盏灯按顺序输入):0(关灯)1(开灯)");fgets(buf,sizeof(buf),stdin);//在终端读取一个字符串buf[strlen(buf)-1]='\0';//因为读到的字符串在最后一个是执行命令的换行符,所以要把最后一个字符替换成'\0'write(fd,buf,sizeof(buf));//将数据传递给内核(将用户空间的buf拷贝到内核空间)}close(fd);return 0;
}

Makefile

modname ?= demo
arch ?= arm
ifeq ($(arch),arm)
#保存UBUNTU内核源码路径
KERNELDIR := /home/ubuntu/FSMP1A/linux-stm32mp-5.10.61-stm32mp-r2-r0/linux-5.10.61/
else
#KERBELDIR保存开发板内核源码路径
KERNELDIR := /lib/modules/$(shell uname -r)/build
endif#PWD保存当前内核模块的路径
PWD := $(shell pwd)
all:
#make modules是模块化编译命令
#make -C $(KERNLEDIR) 执行make之前先切换到KERNELDIR对应的路径
#M=$(PWD)表示进行模块化编译的路径是PWD保存的路径make -C $(KERNELDIR) M=$(PWD) modules
clean:
#编译清除make -C $(KERNELDIR) M=$(PWD) clean
#将obj-m保存的文件单独链接为内核模块
obj-m :=  $(modname).o

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

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

相关文章

YOLOv8改进实战 | 更换主干网络Backbone(四)之轻量化模型MobileNetV3

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…

【Qt之布局】QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout介绍及使用

在Qt中&#xff0c;布局管理器&#xff08;Layout&#xff09;用于管理窗口中的控件的位置和大小&#xff0c;以适应不同大小的窗口。 常用的布局管理器包括QVBoxLayout、QHBoxLayout、QGridLayout和QFormLayout。 先放张布局UI&#xff1a; 1. QVBoxLayout&#xff08;垂直布…

百分点科技受邀参加“一带一路”国际合作高峰论坛

10月17-18日&#xff0c;第三届“一带一路”国际合作高峰论坛在北京成功举行。作为新一代信息技术出海企业代表&#xff0c;百分点科技董事长兼CEO苏萌受邀出席高峰论坛开场活动——“一带一路”企业家大会&#xff0c;与来自82个国家和地区的企业或机构、有关国际组织、经济机…

【IBIS 模型与仿真 - IBISWriter and Write_IBIS】

本文将介绍如何从用户设计中编写自定义IBIS模型。 本文是 SelectIO 解决方案中心&#xff08;Xilinx 答复 50924&#xff09;的设计助手部分&#xff08;Xilinx 答复 50926&#xff09;的一部分。 原文链接&#xff1a;https://support.xilinx.com/s/article/50957?languagee…

2022年亚太杯APMCM数学建模大赛E题有多少核弹可以摧毁地球求解全过程文档及程序

2022年亚太杯APMCM数学建模大赛 E题 有多少核弹可以摧毁地球 原题再现 1945年8月6日&#xff0c;第二次世界大战即将结束。为了尽快结束战争&#xff0c;美国在日本广岛投下了下一颗名为“小男孩”的原子弹。这样一颗原子弹在广岛炸死了20万人&#xff0c;广岛的所有建筑物都…

VueRouter 源码解析

重要函数思维导图 路由注册 在开始之前&#xff0c;推荐大家 clone 一份源码对照着看。因为篇幅较长&#xff0c;函数间的跳转也很多。 使用路由之前&#xff0c;需要调用 Vue.use(VueRouter)&#xff0c;这是因为让插件可以使用 Vue export function initUse(Vue: GlobalAP…

EDUSRC--简单打穿某985之旅

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

idea leetcode配置

idea leetcode配置 配置页面如下图所示&#xff0c;根据需要&#xff0c;填入登录用户名、密码、文件存放路径&#xff0c;注意如果要使用自定义的代码结构配置&#xff0c;要勾选图中框出来的选项。 Code FileName&#xff1a; $!velocityTool.camelCaseName(${question.tit…

CentOS7.9离线安装 Nginx

1. 下载Nginx安装包 下载地址&#xff1a;http://nginx.org/download/nginx-1.20.1.tar.gzhttp://nginx.org/download/nginx-1.20.1.tar.gz 2. 找到Nginx安装时需要的依赖包 我这里是下载了CentOS7.9的安装镜像 阿里下载地址&#xff1a;centos-7.9.2009-isos-x86_64安装包…

Opencv之RANSAC算法用于直线拟合及特征点集匹配详解

Opencv之RANSAC算法用于直线拟合及特征点集匹配详解 讲述Ransac拟合与最小二乘在曲线拟合上的优缺点 讲述在进行特征点匹配时&#xff0c;最近邻匹配与Ransac匹配的不同之处 另外&#xff0c;Ransac也被用于椭圆拟合、变换矩阵求解等 1. 直线拟合 1.1 原理 RANSAC(RANdom …

CUDA 学习记录

1.关于volatile&#xff1a; 对于文章中这个函数&#xff0c; __global__ void reduceUnrollWarps8 (int *g_idata, int *g_odata, unsigned int n) {// set thread IDunsigned int tid threadIdx.x;unsigned int idx blockIdx.x * blockDim.x * 8 threadIdx.x;// convert…

操作系统:线程同步和调度

文章目录 线程同步和调度一、实验目的二、实验要求与内容、过程与结果 系列文章 线程同步和调度 一、实验目的 通过创建线程、分配线程优先级和终止线程的程序设计和调试操作&#xff0c;进一步熟悉操作系统的线程概念&#xff0c;理解Windows 2000线程的生命周期。 通过对事…

18-spring 事务

文章目录 1. xml和注解配置方式的对象2.spring事务传播特性3. 注解事务的初始化流程4. 创建事务信息流程图5. 事务回滚流程图1. xml和注解配置方式的对象 2.spring事务传播特性 事务传播行为类型说明PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事…

RHEL 8.6 Kubespray 1.23.0 install kubernetes v1.27.5

文章目录 1. 预备条件2. download01 节点 安装 dockerdownload01 节点 介质下载下载 bastion01节点配置 yum 源bastion01 节点安装 docker5. 安装 docker insecure registrybastion01 部署 nginx 与 镜像入库13.1 配置 config.sh13.2 配置 setup-docker.sh13.3 配置 start-ngin…

Unity中Shader实现UI流光效果

文章目录 前言一、实现思路1&#xff1a;1、采集两张贴图&#xff0c;一张是主纹理&#xff0c;一张是扫光纹理2、在 v2f 定义一个二维变量 “uv2” 来存放 uv 偏移后的值3、在顶点着色器中&#xff0c;仿照之前的 uv 流动效果,与 _Time相乘后存放于 uv2 中4、最后&#xff0c;…

任务分配问题(回溯法)

算法设计 问题描述 有n&#xff08;n≥1&#xff09;个任务需要分配给n个人执行&#xff0c;每个任务只能分配给一个人&#xff0c;每个人只能执行一个任务。 第i个人执行第j个任务的成本是c[i][j]&#xff08;1≤i&#xff0c;j≤n&#xff09;。求出总成本最小的分配方案 …

【JVM】synchronized与锁升级

文章目录 1. synchronized锁优化背景2. synchronized锁性能优化过程2.1 java5以前2.2 monitor锁2.3 java6开始 3. 无锁4. 偏向锁4.1 背景4.2 理论落地4.3 技术实现4.4 偏向锁的撤销4.5 题外话 5. 轻量级锁5.1 轻量级锁的加锁5.2 轻量级锁的释放5.3 锁升级 6. 重量级锁7. 锁升级…

springweb+vue前后端分离开发,集成部署

背景&#xff1a; 在自己做测试的时候&#xff0c;由于需要项目和项目的前端页面使用同样接口访问&#xff0c;所以需要将前端代码部署到后端项目下。前端采用vue&#xff0c;后端采用springboot。 首先时建立一个vue项目&#xff0c;这个可以参照网上的案例&#xff0c;创建方…

Node.js的安装

直接在浏览器中搜索Node.js即可 打开下载好的文件 验证是否安装成功 在cmd中输入 node -v&#xff0c;若结果为版本号那就是成功的 环境配置 配置全局模块所在的路径缓存cache的路径 在安装目录中新建两个文件夹&#xff0c;文件夹名为:node_cache和node_global 输…

C++之this指针

前言 C中对象模型和this指针是面向对象编程中的重要概念。对象模型描述了对象在内存中的布局和行为&#xff0c;包括成员变量、成员函数的存储方式和访问权限。this指针是一个隐含的指针&#xff0c;指向当前对象的地址&#xff0c;用于在成员函数中引用当前对象的成员变量和成…