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

驱动开发 day4 (led灯组分块驱动)

//编译驱动(注意Makefile的编译到移植到开发板的内核)

        make arch=arm

//清除编译生成文件

        make clean

//安装驱动

        insmod mycdev.ko

//卸载驱动

        rmmod mycdev

//编译fun.c 函数(用到交叉工具编译)

        arm-linux-gnueabihf-gcc fun.c

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

 mycdev.c

#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"struct cdev *cdev;
struct class *cls;
struct device *dev;char kbuf[128] = {0};
unsigned int major = 500;
unsigned int minor = 0; // 次设备号的起始值
dev_t devnum;gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;
// 定义一个自旋锁
spinlock_t lock;int mycdev_open(struct inode *inode, struct file *file)
{int a = inode->i_rdev;file->private_data = (void *)MINOR(a);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;which = (unsigned int)file->private_data;// copy_from_user(&which,(void *)arg,4);// 上锁spin_lock(&lock);switch (cmd){case LED_ON:switch (which){case 0:							  // LED1vir_led1->ODR |= (0x1 << 10); // LED1开灯break;case 1:							  // LED2vir_led2->ODR |= (0x1 << 10); // LED2开灯break;case 2:							 // LED3vir_led3->ODR |= (0x1 << 8); // LED3开灯break;}break;case LED_OFF:switch (which){case 0:vir_led1->ODR &= (~(0X1 << 10));break;case 1:vir_led2->ODR &= (~(0X1 << 10));break;case 2:vir_led3->ODR &= (~(0X1 << 8));break;}break;}// 解锁spin_unlock(&lock);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,.release = mycdev_close,.unlocked_ioctl = mycdev_ioctl,
};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, i;// 初始化上锁spin_lock_init(&lock);// 1.申请对象空间cdev = cdev_alloc();if (NULL == cdev){printk("wangsong申请对象空间失败\n");ret = -EFAULT;goto OUT1;}printk("wangsong申请对象空间成功\n");// 2.初始化对象cdev_init(cdev, &fops);printk("wangsong初始化对象成功\n");// 3.申请设备号if (0 == major){ret = alloc_chrdev_region(&devnum, minor, 3, "wangsong");if (ret){printk("wangsong动态申请设备号失败\n");goto OUT2;}major = MAJOR(devnum);minor = MINOR(devnum);}else{ret = register_chrdev_region(MKDEV(major, minor), 3, "wangsong");if (ret){printk("wangsong静态申请设备号失败\n");goto OUT2;}}printk("wangsong申请设备号成功\n");// 4.注册驱动对象ret = cdev_add(cdev, MKDEV(major, minor), 3);if (ret){printk("wangsong注册驱动对象失败\n");goto OUT3;}printk("wangsong注册驱动对象成功\n");// 5.向上提交目录cls = class_create(THIS_MODULE, "wangsong");if (IS_ERR(cls)){printk("wangsong向上提交目录失败\n");goto OUT4;}printk("wangsong向上提交目录成功\n");// 6.向上提交设备信息for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "wangsong%d", i);if (IS_ERR(dev)){printk("wangsong向上提交设备节点失败\n");ret = -PTR_ERR(dev);goto OUT5;}}printk("wangsong向上提交设备节点成功\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)
{int i;// 取消地址映射iounmap(vir_led1);iounmap(vir_led2);iounmap(vir_rcc);// 1.销毁设备信息for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));printk("wangsong销毁设备信息成功\n");}// 2.销毁目录class_destroy(cls);printk("wangsong销毁目录成功\n");// 3.注销驱动对象cdev_del(cdev);printk("wangsong注销驱动对象成功\n");// 4.释放设备号unregister_chrdev_region(MKDEV(major, minor), 3);printk("wangsong释放设备号成功\n");// 5.释放对象空间kfree(cdev);printk("wangsong释放对象空间成功\n");
}module_init(mycdev_init);module_exit(mycdev_exit);MODULE_LICENSE("GPL");

fun.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <string.h>
#include "head.h"int main(int argc, char const *argv[])
{/* code */int a, b;char buf[128] = {0};printf("调用open\n");int fd0 = open("/dev/wangsong0", O_RDWR);if (fd0 < 0){printf("打开设备文件失败\n");exit(-1);}int fd1 = open("/dev/wangsong1", O_RDWR);if (fd1 < 0){printf("打开设备文件失败\n");exit(-1);}int fd2 = open("/dev/wangsong2", O_RDWR);if (fd2 < 0){printf("打开设备文件失败\n");exit(-1);}while (1){// 从终端读取printf("请输入要点亮的灯号(1-3)+操作(0[灭]、1[亮])[exit退出程序]:");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = '\0';if (!strcmp(buf, "exit"))break;a = (int)buf[1] - 48;b = (int)buf[0] - 48;printf("a=%d,b=%d", a, b);if (a == 1){switch (b){case 1:if (ioctl(fd0, LED_ON, &b)){printf("开灯失败\n");}break;case 2:if (ioctl(fd1, LED_ON, &b)){printf("开灯失败\n");}break;case 3:if (ioctl(fd2, LED_ON, &b)){printf("开灯失败\n");}break;default:printf("格式错误请重新输入>>>\n");}}else{switch (b){case 1:if (ioctl(fd0, LED_OFF, &b)){printf("关灯失败\n");}break;case 2:if (ioctl(fd1, LED_OFF, &b)){printf("关灯失败\n");}break;case 3:if (ioctl(fd2, LED_OFF, &b)){printf("关灯失败\n");}break;default:printf("格式错误请重新输入>>>\n");}}}printf("调用close\n");close(fd0);close(fd1);close(fd2);return 0;
}

Makefile

modname ?= mycdevarch ?= armifeq ($(arch),arm)
KERNELDIR:= /home/ubuntu/13_UBOOT/linux-stm32mp-5.10.61-stm32mp-r2-r0/linux-5.10.61
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build/
endifPWD:=$(shell pwd)all:make -C $(KERNELDIR) M=$(PWD) modulesclean:make -C $(KERNELDIR) M=$(PWD) cleanobj-m:=$(modname).o

相关文章:

驱动开发 day4 (led灯组分块驱动)

//编译驱动(注意Makefile的编译到移植到开发板的内核) make archarm //清除编译生成文件 make clean //安装驱动 insmod mycdev.ko //卸载驱动 rmmod mycdev //编译fun.c 函数(用到交叉工具编译) arm-linux-gnueabihf-gcc fun.c head.h #ifndef __HEAD_H__ #define __HEAD_H__…...

electron dialog.showMessageBox使用案例

electron 版本&#xff1a;25.3.1 index.html <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>Hello World!</title><meta http-equiv"Content-Security-Policy" content"script-src self unsa…...

代码随想录算法训练营第二十二天 | 读PDF复习环节2

读PDF复习环节2 本博客的内容只是做一个大概的记录&#xff0c;整个PDF看下来&#xff0c;内容上是不如代码随想录网站上的文章全面的&#xff0c;并且PDF中有些地方的描述&#xff0c;是很让我疑惑的&#xff0c;在困扰我很久后&#xff0c;无意间发现&#xff0c;其网站上的讲…...

TimescaleDB时序数据库初识

注&#xff1a;本文翻译自https://legacy-docs.timescale.com/v1.7/introduction TimescaleDB是一个开源时间序列数据库&#xff0c;针对快速摄取和复杂查询进行了优化。它说的是“完整的SQL”&#xff0c;因此像传统的关系数据库一样易于使用&#xff0c;并且以以前为NoSQL数…...

Numpy-聚合函数

NumPy 提供了很多统计函数&#xff0c;用于从数组中查找最小元素&#xff0c;最大元素&#xff0c;百分位标准差和方差等。 函数名说明np.sum()求和np.prod()所有元素相乘np.mean()平均值np.std()标准差np.var()方差np.median()中位数np.power()幂运算np.sqrt()开方np.min()最小…...

企业博客资讯如何高效运营起来?

运营一个高效的企业博客资讯需要综合考虑多个因素&#xff0c;包括内容策划、发布频率、优化推广、互动反馈等。下面将从这些方面介绍如何高效运营企业博客资讯。 如何高效运营企业博客资讯 内容策划 首先&#xff0c;需要制定一个明确的内容策略。确定博客的定位和目标受众…...

跟我学c++中级篇——模板的继承

一、继承 面向对象编程有三个特点&#xff1a;封装、继承和多态。其中继承在其中起着承上启下的作用。一般来说&#xff0c;继承现在和组合的应用比较难区分&#xff0c;出于各种场景和目的&#xff0c;往往各有千秋。但目前主流的观点&#xff0c;一般是如果没有特殊情况&…...

需求分析案例:消息配置中心

本文介绍了一个很常见的消息推送需求&#xff0c;在系统需要短信、微信、邮件之类的消息推送时&#xff0c;边界如何划分和如何设计技术方案。 1、需求 一个系统&#xff0c;一般会区分多个业务模块&#xff0c;并拆分成不同的业务系统&#xff0c;例如一个商城的架构如下&am…...

自动化测试——环境

一、搭建环境 1、安装Slenium pip install selenium 2、安装浏览器驱动-》查询浏览器版本-》下载对应版本驱动-》在path路径中配置&#xff08;浏览器更新需要重新下载&#xff09; pip install webdriver -helper&#xff08;自动化&#xff09;python3.9以上 pip install 安…...

短视频矩阵营销系统技术开发者开发笔记分享

一、开发短视频seo抖音矩阵系统需要遵循以下步骤&#xff1a; 1. 确定系统需求&#xff1a;根据客户的需求&#xff0c;确定系统的功能和特点&#xff0c;例如用户注册登录、视频上传、视频浏览、评论点赞等。 2. 设计系统架构&#xff1a;根据系统需求&#xff0c;设计系统的…...

vue2和vue3引用ueditor的区别

官方文档入口 UEditor Docs vue2使用方式 UE.vue组件 <template><div><script id"editor" type"text/plain"></script><Upload v-if"isupload" :config"{total:9}" :isupload"isupload" ret…...

【每日运维】RockyLinux8非容器化安装Mysql、Redis、RabitMQ单机环境

系统版本&#xff1a;RockyLinux 8.6 安装方式&#xff1a;非容器化单机部署 安装版本&#xff1a;mysql 8.0.32 redis 6.2.11 rabbitmq 3.11.11 elasticsearch 6.7.1 前置条件&#xff1a;时间同步、关闭selinux、主机名、主机解析host 环境说明&#xff1a;PC电脑VMware Work…...

第一次后端复习整理(JVM、Redis、反射)

1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM&#xff0c;JVM超详细解析&#xff01;&#xff01;&#xff01; 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…...

python的web学习(一)-初识django

文章目录 软件创建项目默认项目文件说明App的概念(应用)apps.py编写URL和视图函数对应关系【urls.py】编写视图函数【views.py】启动服务 软件 python下载 django下载 创建项目 django-admin startproject 文件名默认项目文件说明 项目名 manage.py(项目管理&#xff0c;启…...

JavaWeb+jsp+Tomcat的叮当书城项目

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88123111?spm1001.2014.3001.5503 技术&#xff1a;ssm jsp JDK1.8 MySQL5.7 Tomcat8.3 源码数据库课程设计 功能&#xff1a;管理员与普通用户和超级管理员三个角色&#xff0c;管理员可…...

【嵌入式Linux系统开发】——系统移植概述

目录 &#x1f349;&#x1f349;一、什么是嵌入式系统 &#x1f349;&#x1f349;二、嵌入式系统操作 &#x1f349;&#x1f349;三、嵌入式Linux的特点 &#x1f349;&#x1f349;四、嵌入式系统的组成 1、硬件和软件 2、硬件层 3、中间层 4、软件层 5、 功能层与执…...

升讯威在线客服系统是如何实现对 IE8 完全完美支持的(怎样从 WebSocket 降级到 Http)【干货】

简介 升讯威在线客服与营销系统是基于 .net core / WPF 开发的一款在线客服软件&#xff0c;宗旨是&#xff1a; 开放、开源、共享。努力打造 .net 社区的一款优秀开源产品。 完整私有化包下载地址 &#x1f4be; https://kf.shengxunwei.com/freesite.zip 当前版本信息 发布…...

用VMware给运行在VMware上的CentOS7生成一个以SSH方式连接VMware上的CentOS7的运行在Windows上的命令行窗口

2023年7月27日&#xff0c;周四早上 目录 一个发现生成方法如果上面的方法连接失败&#xff0c;就采取这个方法 一个发现 今天早上无意间发现VMware可以生成一个以SSH方式连接着CentOS7的Windows命令行窗口&#xff0c; 这样做可以带来一定的便利性 &#xff1a; 方便复制、…...

C语言基础-3

1、函数 函数是C语言代码的基本组成部分&#xff0c;它是一个小的模块&#xff0c;整个程序由很多个功能独立的模块&#xff08;函数&#xff09;组成。这就是程序设计的基本分化方法。 main&#xff1a;C语言中所谓的主函数&#xff0c;主函数就是一种特别的函数。特别之处在于…...

Python 编程规范进阶(1) | 命名规范

养成良好的开发、编程习惯 跟着google开源项目走 https://github.com/google/styleguide 近期Target&#xff1a; 命名规范&#xff1b; Pythonic 积累 按照需求写需要的API&#xff1b; 写前先动脑子&#xff0c;比如画流程图&#xff0c;测试接口&#xff1b; Google 推荐的P…...

算法----二叉搜索树中第K小的元素

题目 二叉搜索树中第K小的元素 给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 个最小元素&#xff08;从 1 开始计数&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,null,2], k 1 输出&#xff…...

阿里Java开发手册~安全规约

1. 【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。 说明&#xff1a; 防止没有做水平权限校验就可随意访问、修改、删除别人的数据&#xff0c;比如查看他人的私信 内容、修改他人的订单。 2. 【强制】用户敏感数据禁止直接展示&#xff0c;必须对展示数据进…...

消息中间件RabbitMQ——学习笔记

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…...

爬虫005_python类型转换_其他类型转换为整型_转换为Float类型_转换为字符串_转换为布尔值---python工作笔记023

首先来看,字符串转换成int 很简单 float转换成int 会把小数点后面的内容丢掉 boolean转换为int true是1 false 是0 然后字符串转换为int,要注意 不能有特殊字符比如1.23 中有点 就报错 上面字符串12ab,有ab也报错 看上面...

SpringBoot复习:(5)使用PropertySource注解

一、自定义的一个配置文件 age33 nameliu二、实体类 package com.example.demo.domain;public class Student {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {retur…...

webrtc 支持H265(三) 总结

文章目录 web端的解码及渲染的实现应用场景单向视频流的场景datachannel通道的稳定性解码性能 双向视频流的场景有音频流的场景 web端的解码及渲染的实现 在前面的文章中介绍了ZLMediaKit的修改方法&#xff0c;在web端的播放器可以参照这个实现&#xff0c;基于wasm H265播放…...

Windows使用Notepad++编辑Linux服务器的文件

&#x1f680; Windows使用Notepad编辑Linux服务器的文件 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介…...

升级你的数据采集引擎 使用多线程与代理池提升HTTP代理爬虫性能

在信息爆炸的时代&#xff0c;海量数据的采集和分析成为了企业发展和决策的关键。本文将分享如何通过多线程和代理池的应用&#xff0c;助您升级数据采集引擎&#xff0c;提高数据获取效率和稳定性。 HTTP代理爬虫作为数据采集的重要工具&#xff0c;其性能直接影响着数据采集…...

flask实现一个登录界面

flask实现一个登录界面 基础的Flask项目结构 forms.py&#xff1a;定义登录表单和表单字段的文件。templates/login.html&#xff1a;用于渲染登录表单的 HTML 模板文件。routes.py&#xff1a;定义应用的路由和视图函数的文件。__init__.py&#xff1a;创建并初始化 Flask 应…...

redis的四种模式优缺点

redis简介 Redis是一个完全开源的内存数据结构存储工具&#xff0c;它支持多种数据结构&#xff0c;以及多种功能。Redis还提供了持久化功能&#xff0c;可以将数据存储到磁盘上&#xff0c;以便在重启后恢复数据。由于其高性能、可靠性和灵活性&#xff0c;Redis被广泛应用于…...