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

Rk3568驱动开发_驱动实现流程以及本质_3

1设备号:

在这里插入图片描述
cat /proc/devices

编写驱动模块需要要想加载到内核并与设备正常通信,那就需要申请一个设备号,用cat /proc/devices可以查看已经被占用的设备号

设备号有什么用?不同设备其驱动实现不同用设备号去区分,例如字符驱动键盘,块设备驱动固态硬盘,这两种设备不同驱动实现方式不同所以用不同主设备号区分,什么会是从设备号?例如串口,一台电脑接入两根串口,这俩串口用的驱动是一样的,但是要区分不同的串口,就用从设备号区分

2.注册节点:

为什么要注册节点?Linux上一切皆文件,例如你写了串口驱动,你要调用接到你电脑上的串口,串口接到你的电脑上电脑识别后就会创建这样一个节点,供open函数打开串口做后续操作

在这里插入图片描述

目前刚学习是手动创建,后面估计会用一些方法自动创建

3.实现流程:

驱动代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>#define CHREDEVBASE_MAJOR 200  // 主设备号
#define CHRDEVNAME  "chrdevbase"  // 名字static int chrdevbase_open(struct inode* inode, struct file* filp){printk("chrdevbase_open\r\n");return 0;
}static int chrdevbase_release(struct inode* inode, struct file* filp){printk("chrdevbase_release\r\n");return 0;
}static ssize_t chrdevbase_read(struct file* filp, __user char* buf, size_t count, loff_t* ppos){printk("hrdevbase_read\r\n");return 0;                
}static ssize_t chrdevbase_write(struct file* filp, const char __user *buf, size_t count, loff_t* ppos){printk("chrdevbase_write\r\n");return 0;
}// 字符设备操作集合
static struct file_operations chrdevbase_fops={.owner = THIS_MODULE,       // 属于这个驱动模块.open = chrdevbase_open,.release = chrdevbase_release,.read = chrdevbase_read,.write = chrdevbase_write,
};static int __init chrdevbase_init(void){   int ret = 0;printk("chrdevbase_init\r\n");// 注册字符设备ret = register_chrdev(CHREDEVBASE_MAJOR, CHRDEVNAME, &chrdevbase_fops);if(ret < 0){printk("chrdevbase init failed\r\n");unregister_chrdev(CHREDEVBASE_MAJOR, CHRDEVNAME);}return 0;
}static void __exit chrdevbase_exit(void){printk("chrdevbase_exit\r\n");
}// 核心修正点:添加以下声明
MODULE_LICENSE("GPL");          // 必须声明许可证(例如GPL)
MODULE_AUTHOR("Narnat");      // 可选:作者信息
MODULE_DESCRIPTION("chrdevbase"); // 可选:模块描述// 模块入口与出口
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

makefile:

# 设置绝对路径(避免相对路径引发的错误)
KERNELDIR := /home/saisi/RK3568/SDK/linux/rk3568_linux_sdk/kernel
CURRENT_PATH := $(shell pwd)# 必须明确指定架构和交叉编译器!!!
ARCH := arm64
# 关键修正点:使用ARM官方工具链的正确前缀和路径
TOOLCHAIN_PATH := /usr/local/arm-gnu-toolchain-12.3.rel1-x86_64-aarch64-none-linux-gnu/bin
CROSS_COMPILE := $(TOOLCHAIN_PATH)/aarch64-none-linux-gnu-# 模块名称
obj-m := chrdevbase.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modulesclean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) ARCH=$(ARCH) cleanrm -rf app
app:/usr/local/arm-gnu-toolchain-12.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc chrdevbaseApp.c -o app

app代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main(int argc, char* argv[]){int ret = 0;int fd;char readbuf[10], writebuf[50];char* filename;filename = argv[1];fd = open(filename, O_RDWR);if(fd < 0){printf("cant open file %s\r\n", filename);return -1;}ret =  read(fd, readbuf, 10);if(ret < 0){printf("read file %s failed\r\n", filename);return -1;}ret = write(fd, writebuf, 50);if(ret < 0){printf("write file %s failed!\r\n", filename);}close(fd);return 0;
}

驱动代码中register_chrdev和unregister_chrdev是用于注册字符驱动和注销字符驱动的函数,也就是指明你的驱动类型其中要指定你的主设备号和名字把这些写好后挂载模块后能在系统里找到你注册的信息

在这里插入图片描述
lsmod显示的只是你的这个模块名字

在这里插入图片描述

注意:注册完节点后,我们的这个驱动会被当做一个文件,就像linux上的摄像头设备一样/dev/video0也是一个文件

在这里插入图片描述
用我们写的程序在应用层去打开、读、写的时候本质会调用到我们自己写的驱动

在这里插入图片描述

这张图片的含金量还在增加

在这里插入图片描述

4.最后总结:

Linux中为何一切皆文件?open函数打开txt文件调用的是读取txt文件的函数,open函数打开串口是调用串口的驱动函数,打开chrdevbase文件就是调用我们自己写的驱动函数,也就是说每一个设备都有其对应的实现驱动模块,open打开他的时候就会去调用这个接口,我们要做的就是实现这些驱动的接口,创建一个节点/dev节点也就是所谓文件,open调用这个文件的时候能正确的调用我们的驱动模块,实现我们的目的

最开始没有学驱动的时候我摸不着头脑,觉得驱动它遥不可及,当我真正下定决心去学的时候当我迈出第一步的时候我发现它并非不可能,无论是学习还是人生,最难的应该是迈出第一步,试试呗

相关文章:

Rk3568驱动开发_驱动实现流程以及本质_3

1设备号&#xff1a; cat /proc/devices 编写驱动模块需要要想加载到内核并与设备正常通信&#xff0c;那就需要申请一个设备号&#xff0c;用cat /proc/devices可以查看已经被占用的设备号 设备号有什么用&#xff1f;不同设备其驱动实现不同用设备号去区分&#xff0c;例如字…...

【学习笔记】LLM+RL

文章目录 1 合成数据与模型坍缩&#xff08;model collapse&#xff09;,1.1 递归生成数据与模型坍缩1.2 三种错误1.3 理论直觉1.4 PPL指标 2 基于开源 LLM 实现 O1-like step by step 慢思考&#xff08;slow thinking&#xff09;&#xff0c;ollama&#xff0c;streamlit2.1…...

深入理解IP子网掩码子网划分{作用} 以及 不同网段之间的ping的原理 以及子网掩码的区域划分

目录 子网掩码详解 子网掩码定义 子网掩码进一步解释 子网掩码的作用 计算总结表 子网掩码计算 子网掩码对应IP数量计算 判断IP是否在同一网段 1. 计算步骤 2. 示例 3. 关键点 总结 不同网段通信原理与Ping流程 1. 同网段通信 2. 跨网段通信 网段计算示例 3. P…...

rust 前端npm依赖工具rsup升级日志

rsup是使用 rust 编写的一个前端 npm 依赖包管理工具&#xff0c;可以获取到项目中依赖包的最新版本信息&#xff0c;并通过 web 服务的形式提供查看、升级操作等一一系列操作。 在前一篇文章中&#xff0c;记录初始的功能设计&#xff0c;自己的想法实现过程。在自己的使用过…...

2.2 STM32F103C8T6最小系统板的四种有关固件的开发方式

2.2.1 四种有关固件的开发方式 四种有关于固件的开发方式从时间线由远及近分别是&#xff1a;寄存器开发、标准外设驱动库开发、硬件抽象层库开发、底层库开发。 四种开发方式各有优缺点&#xff0c;可以参考ST官方的测试与说明。 1.寄存器开发 寄存器编程对于从51等等芯片过渡…...

【C++】 stack和queue以及模拟实现

一、stack及其模拟实现 1.1 stack介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行 元素的插入与提取操作。stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容器&am…...

python与C系列语言的差异总结(2)

Python有很多表达布尔值的方式&#xff0c;布尔常量False、0、Python零值None、空值&#xff08;如空的列表[]和空字符串""&#xff09;&#xff0c;都被视为False。布尔常量True和其他一切值都被视为True。但不相等。这个自由度相比C类语言更加高。 if (not None):…...

Linux之文件系统

1.前言 文件 内容属性 文件分为被打开的文件&#xff08;跟基础IO有关&#xff0c;在内存上&#xff09;和没有被打开的文件(在磁盘上)。 在磁盘上找没有被打开的文件属于文件系统的工作 2.对硬件的理解 2.1 磁盘&#xff0c;服务器&#xff0c;机柜&#xff0c;机房 1.磁…...

LeetCode刷题 -- 23. 合并 K 个升序链表

小根堆排序与合并 K 个有序链表的实现 1. 介绍 本技术文档详细介绍了如何使用 小根堆&#xff08;Min Heap&#xff09; 实现 K 个有序链表的合并。 核心思想是&#xff1a; 使用 小根堆 维护当前最小的节点。每次取出堆顶元素&#xff08;最小值&#xff09;加入合并链表&…...

DeepSeek在MATLAB上的部署与应用

在科技飞速发展的当下&#xff0c;人工智能与编程语言的融合不断拓展着创新边界。DeepSeek作为一款备受瞩目的大语言模型&#xff0c;其在自然语言处理领域展现出强大的能力。而MATLAB&#xff0c;作为科学计算和工程领域广泛应用的专业软件&#xff0c;拥有丰富的工具包和高效…...

mapbox基础,使用geojson加载fill-extrusion三维填充图层

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️fill-extrusion三维填充图层样式二、�…...

基于 SpringBoot 的 “电影交流平台小程序” 系统的设计与实现

大家好&#xff0c;今天要和大家聊的是一款基于 SpringBoot 的 “电影交流平台小程序” 系统的设计与实现。项目源码以及部署相关事宜请联系我&#xff0c;文末附上联系方式。 项目简介 基于 SpringBoot 的 “电影交流平台小程序” 系统设计与实现的主要使用者分为 管理员 和…...

单片机裸机编程-时机管理

对于 RTOS 实时操作系统&#xff0c;我们是通过 TASK&#xff08;任务&#xff09;进行底层操作的&#xff0c;这与裸机编程中的函数&#xff08;fun&#xff09;类似。不同的任务或函数实现不同的功能&#xff0c;在RTOS中&#xff0c;单片机有信号量、队列等不同任务之间的通…...

Flutter系列教程之(2)——Dart语言快速入门

目录 1.变量与类型 1.1 num类型 1.2 String类型 1.3 Object与Dynamic 1.4 类型判断/转换 1.5 变量和常量 2.方法/函数 3.类、接口、抽象类 3.1 类 3.2 接口 4.集合 4.1 List 4.2 Set 4.3 Map 5.总结 Dart语言的语法和Kotlin、Java有类似之处&#xff0c;这里就通…...

pyecharts介绍

文章目录 介绍安装pyecharts基本使用全局配置选项 折线图相关配置地图模块使用柱状图使用 介绍 echarts虑是个由百度开源的数据可视化&#xff0c;凭借着良好的交互性&#xff0c;精巧的图表设计&#xff0c;得到了众多开发者的认可&#xff0c;而Pyhon是门富有表达力的语言&a…...

前缀和相关题目记录(未完待续...)

1 前缀和 一维前缀和是指对于一个数组 a a a&#xff0c;我们定义一个新的数组 s s s&#xff0c;其中每个元素 s [ i ] s[i] s[i] 表示从数组开头到第 i i i 个元素的累加和&#xff1a; s [ i ] a [ 1 ] a [ 2 ] ⋯ a [ i ] ∑ j 1 i a [ j ] s[i] a[1] a[2] \…...

Https解决了Http的哪些问题

部分内容来源&#xff1a;小林coding 详细解析 Http的风险 HTTP 由于是明文传输&#xff0c;所以安全上存在以下三个风险&#xff1a; 1.窃听风险 比如通信链路上可以获取通信内容&#xff0c;用户号容易没。 2.篡改风险 比如强制植入垃圾广告&#xff0c;视觉污染&#…...

OpenCV给图像添加噪声

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 如果你已经有了一张干净的图像&#xff0c;并希望通过编程方式向其添加噪声&#xff0c;可以使用 OpenCV 来实现这一点。以下是一个简单的例子&a…...

湖北中医药大学谱度众合(武汉)生命科技有限公司研究生工作站揭牌

2025年2月11日&#xff0c;湖北中医药大学&谱度众合&#xff08;武汉&#xff09;生命科技有限公司研究生工作站揭牌仪式在武汉生物技术研究院一楼101会议室举行&#xff0c;湖北中医药大学研究生院院长刘娅教授、基础医学院院长孔明望教授、基础医学院赵敏教授、基础医学院…...

欢乐力扣:快乐数

文章目录 1、题目描述2、思路1代码 1、题目描述 快乐数。  编写一个算法来判断一个数 n 是不是快乐数。  快乐数定义为&#xff1a;对于一个正整数&#xff0c;每次不断将其转化成 每位数字的平方和。 判断是否最终和会为1&#xff0c;是1就是快乐数&#xff0c;否则不是。 …...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...