树莓派驱动编译

        驱动编译前提:驱动代码的编译需要提前编译号的内核

驱动(3种实现方法,2条路线)_驱动编写三种方法-CSDN博客

驱动的编写_驱动编写-CSDN博客

一、概念

1.1、驱动认识
        1、裸机程序中是直接操控硬件的,操作系统中必须通过驱动来操控硬件。这两个的本质区别就是分层
        2、linux驱动本身做了模块化设计,linux驱动本身和linux内核不是强耦合的
        3、驱动的设计中有一个关键数据结构(结构体),结构体中包含一些变量和一些函数指针
                变量用来记录驱动相关的一些属性,函数指针用来记录驱动相关的操作方法
                这些变量和函数指针加起来就构成了驱动。驱动就被抽象为这个结构体
        4、一个驱动工作时主要就分几部分:驱动构建(构建一个struct mmc然后填充它)
                驱动运行时(调用这些函数指针指针的函数和变量)
        5、分离思想
                分离思想就是说在驱动中将操作方法和数据分开
                操作方法就是函数,数据就是变量
                在不同的地方来存储和管理驱动的操作方法和变量,这样的优势就是驱动便于移植。
        6、分层思想
                分层思想是指一个整个的驱动分为好多个层次
                简单理解就是驱动分为很多个源文件,放在很多个文件夹中

1.2、什么是驱动

        1、设备和用户之间的桥梁,内核结构由用户级,内核级,硬件级

        2、驱动,操作硬件部分代码

1.3、驱动分为3种,及区别

        1、字符设备,以字节为单位读写串口,led等        

        2、块设备,以块为单位读写,sd卡等

        3、网络设备,网卡,socket等

1.4、模块化

        1、宏内核:操作系统是整体,紧耦合,直接调用函数,简单高效

                微内核:相当于是多个进程,一个错误不会影响其他,Windows

        2、静态模块化:程序编译内核,编译时可裁剪,加模块要重新编译烧录

                动态模块化:加模块,不需要重新编译

1.5、安全性

        1、驱动程序崩溃,内核可能崩溃

        2、驱动效率影响内核效率

        3、安全,漏洞
                未初始化,例如函数指针
                恶意用户程序,利用驱动的漏洞,例如传参
                缓冲区溢出,例如超出缓存区大小
                竞争状态,自旋锁等

1.6、应用驱动硬件的流程

        APP------>调用C库种(open,write,read)等函数产生软中断(中断号0x80),从用户空间进入到内核空间--------->sys_call函数根据驱动被设备名去找到设备号---------->虚拟文件系统VAFS(sys_open,sys_write)去找相应驱动引脚的驱动文件open------------->驱动文件open直接操作寄存器

1.7、设备文件

        1、各种设备以文件的形式存放在**/dev目录,称设备文件**

        2、主设备号,次设备号

                1、主设备号:不同的设备(硬盘,led)

                2、次设备号:同一类的多个设备(led1,led2)

1.8、驱动链表,数组        (驱动插入链表的顺序由设备号检索)

        1、管理所有设备的驱动

        2、添加(驱动插入链表顺序由设备号检索)
                编写驱动,加载到内核
                设备名,设备号,设备驱动函数:操作寄存器来驱动I/O

        3、查找 调用
                调用驱动程序,用户应用去open

1.9、

1.9、udev机制
        1、udev是一个设备管理工具,udev以守护进程的形式运行
        2、通过侦听内核发出来的uevent来管理/dev目录下的设备文件。
        3、udev在用户空间运行,而不在内核空间运行。
        4、它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。
        5、udev会根据/etc/udev/udev.conf文件中的udev_rules指定的目录,逐个检查该目录下的

                文件,这个目录下的文件都是针对某类或某个设备应该施行什么措施的规则文件。

二、实现一个驱动代码

        1、添加驱动需要什么

                1、设备名

                2、设备号

                3、驱动代码

        2、假设树莓派dev目录下已经存在了一个 pin4的驱动

                应用层访问/dev/pin4驱动代码           

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#include <stdio.h>int main()
{int fd;char ch = '1';fd = open("/dev/pin4" ,O_RDWR);if (-1 == fd){perror("erron");printf("open failed!\n");}else{printf("open success\n");}fd = write(fd , (void *)&ch ,1);return 0;
}

                3、写一个字符设备驱动

                        因为驱动程序是通过驱动链表进行添加的,首先开发需要拿到固定驱动框架,下面是一个字符驱动框架

#include <linux/fs.h>                    //file_operations声明
#include <linux/module.h>                //module_init module_exit声明
#include <linux/init.h>                  //__init __exit 宏定义声明
#include <linux/device.h>                //class device声明
#include <linux/uaccess.h>               //copy_from_user的头文件
#include <linux/types.h>                 //设备号 dev_t 类型声明
#include <asm/io.h>                      //iorsemap iorsemap的头文件static struct class *pin4_class;
static struct device *pin4_class_dev;static dev_t devno;                      //设备号
static int major=231;                     //主设备号
static int minor = 0;                    //次设备号
static char *module_name = "pin4";       //模块名static ssize_t pin4_read(struct file *file ,char __user *buf,size_t size ,loff_t *ppos)
{printk("pin4_read\n");return 0;
}// led_open函数
static int pin4_open(struct inode *inode, struct file *file)
{printk("pin4_open\n");  //内和打印函数和printf差不多,可以用dmesg命令查看内核的打印return 0;
}//led_write函数
static ssize_t pin4_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos)
{printk("pin4_write\n");return 0;
}//    这个结构结构体会被注册进驱动链表
static struct file_operations pin4_fops ={    .owner = THIS_MODULE,//将对应的函数关联在file_operations的结构体中.open  = pin4_open,.write = pin4_write,.read  = pin4_read,
};int __init pin4_drv_init(void)       //真实驱动入口
{  int ret;devno = MKDEV(major,minor);      //创建设备号ret = register_chrdev(major, module_name, &pin4_fops);  //注册驱动,告诉内核 把这个驱动加到内核的链表中pin4_class = class_create( THIS_MODULE,"myfirstdemo");   //让代码在dev自动生成设备  pin4_class_dev = device_create(pin4_class,NULL,devno,NULL,module_name);//创建设备文件return 0;
}void __exit pin4_drv_exit(void)
{device_destroy(pin4_class,devno);class_destroy(pin4_class);unregister_chrdev(major,module_name);   //卸载驱动}module_init(pin4_drv_init);     // 入口,内核加载该驱动的时候,这个宏会被调用
module_exit(pin4_drv_exit);     
MODULE_LICENSE("GPL v2");

        3、对驱动代码进行编译(驱动可以编译成模块或编译进内核)

        把写的驱动代码复制到下载的Linux源码文件里的drviers/char字符驱动设备下

        更改Makefile文件                将驱动编译成模块

        编译驱动代码

ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules

         交叉编译调用该驱动的应用层文件,并将驱动模块文件和应用层文件都考入树莓派

        加载内核驱动

sudo insmod pin4drivers.kolsmod       //这个命令可以查看内核驱动模块
rmmod       //删除驱动模块  例:rmmod pin4drivers  

         运行驱动测试代码

    sudo ~/pin4testdmesg  查看内核打印的信息

        应用层调用驱动

         引用层open通过文件名找到驱动的设备号————>产生软中断,调用sys_call————>调用虚拟文件系统的sys_open通过设备号去驱动链表找到相应的硬件驱动文件————>执行驱动文件里面的open。

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

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

相关文章

力扣-跳跃游戏

问题 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 解答 class Solu…

C++ 入门(八)— 常量和字符串

常量和字符串 常量变量常量表达式编译时优化 Constexpr 变量std::string字符串输出 std::coutstd::string可以处理不同长度的字符串字符串输入 std::cin用于输入文本std::getline()不要按值传递Constexpr 字符串 std::string_view可以使用许多不同类型的字符串进行初始化可以接…

v69.字符

1.字符类型 1.1 可以将char类型的变量赋值为整数&#xff0c;也可以赋值为字符! 注意字符要用单引号 ’ ’ 而不是双引号 每一个字符在计算机内部都有一个值去表达它。字符’1’ 在计算机里表示的十进制的整数值为49&#xff0c;就像’A’表示十进制值65。 1.2 scanf 与 p…

C++面试宝典第33题:数组组成最大数

题目 给定一组非负整数nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。 示例1: 输入:nums = [10, 2] 输出:"210" 示例2: 输入:nums = [3, 30, 34, 5, 9] 输出:"…

【查漏补缺你的Vue基础】Vue数据监听深度解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【rust】10 project、crate、mod、pub、use、项目目录层级组织、概念和实战

文章目录 一、项目目录层级组织概念1.1 cargo new 创建同名 的 Project 和 crate1.2 多 crate 的 package1.3 mod 模块1.3.1 创建嵌套 mod1.3.2 mod 树1.3.3 用路径引用 mod1.3.3.1 使用绝对还是相对? 1.3.4 代码可见性1.3.4.1 pub 关键字1.3.4.2 用 super 引用 mod1.3.4.3 用…

阿里Java开发手册(黄山版) LeetCode刷题手册 免费下载

目录 一、阿里Java开发手册(黄山版) 二、LeetCode刷题手册 三、获取方式 今天给大家推荐两个程序员的辅助利器&#xff01;都是平时开发&#xff0c;刷算法能经常用到的书籍&#xff0c;怕百度云分享会失效&#xff0c;获取方式在最下面&#xff0c;永久有效。 一、阿里Jav…

C++ 反向迭代器的设计与实现

在本文开始之前&#xff0c;先明晰几个 关键词 的含义&#xff08;T : 模板参数&#xff09;&#xff1a; Ref : T& / const T&Ptr : T* / const T* 一、反向迭代器设计的上帝视角 我们希望将 反向迭代器 设计成一种适配器——传 list::iterator 得到 list 的反向迭代…

Lastools工具使用

Lastools工具使用 1、介绍 官网链接 常用的功能 las2las可以进行点云拼接las2txt可以将点云中的有效信息转换为txt文档&#xff08;如xyz坐标&#xff09;lasmerge可以将多个LAS/LAZ文件合并为一个文件Laszip将LAS文件高速压缩到LAZ而不会丢失信息las2text将LAS/LAZ转换为可…

C++初阶:模版相关知识的进阶内容(非类型模板参数、类模板的特化、模板的分离编译)

结束了常用容器的介绍&#xff0c;今天继续模版内容的讲解&#xff1a; 文章目录 1.非类型模版参数2.模板的特化2.1模版特化引入和概念2.2函数模版特化2.3类模板特化2.3.1全特化2.3.1偏特化 3. 模板分离编译3.1分离编译概念3.2**模板的分离编译**分析原因 1.非类型模版参数 模板…

设计模式(五)-观察者模式

前言 实际业务开发过程中&#xff0c;业务逻辑可能非常复杂&#xff0c;核心业务 N 个子业务。如果都放到一块儿去做&#xff0c;代码可能会很长&#xff0c;耦合度不断攀升&#xff0c;维护起来也麻烦&#xff0c;甚至头疼。还有一些业务场景不需要在一次请求中同步完成&…

如何在Linux系统Docker部署Wiki.js容器并结合内网穿透实现远程访问本地知识库

文章目录 1. 安装Docker2. 获取Wiki.js镜像3. 本地服务器打开Wiki.js并添加知识库内容4. 实现公网访问Wiki.js5. 固定Wiki.js公网地址 不管是在企业中还是在自己的个人知识整理上&#xff0c;我们都需要通过某种方式来有条理的组织相应的知识架构&#xff0c;那么一个好的知识整…

适用Java SpringBoot项目的分布式锁

在分布式系统中&#xff0c;常用到分布式锁&#xff0c;它有多中实现方式&#xff0c;如&#xff1a;基于redis&#xff0c;database&#xff0c;zookeeper等。Spring integration组件有这三种服务的分布式锁实现&#xff0c;今天来看看用的比较多的redis和database实现方式。 …

【EI会议征稿通知】2024年第三届生物医学与智能系统国际学术会议(IC-BIS 2024)

2024年第三届生物医学与智能系统国际学术会议&#xff08;IC-BIS 2024&#xff09; 2024 3rd International Conference on Biomedical and Intelligent Systems (IC-BIS 2024) 2024年第三届生物医学与智能系统国际学术会议&#xff08;IC-BIS 2024&#xff09; 将于2024年4月…

为什么推荐使用ref而不是reactive

为什么推荐使用ref而不是reactive 局限性问题&#xff1a; reactive本身存在一些局限性&#xff0c;可能会在开发过程中引发一些问题。这需要额外的注意力和处理&#xff0c;否则可能对开发造成麻烦。数据类型限制&#xff1a; reactive声明的数据类型仅限于对象&#xff0c;而…

Html零基础入门教程(非常详细)

文章目录 1.认识HTML2.html 框架3.HTML常见标签4.HTML语法特征5.列表 1.认识HTML html是超文本标记语言: 目前最新版本是html5,由w3c(万维网联盟)完成标准制定。 声明文档的类型是html5 超文本标记语言。 HTML &#xff0c;全称“Hyper Text Markup Language&#xff08;超文…

LNMP架构(搭建论坛+博客)

目录 一、LNMP架构概述 1、LNMP架构的概念 2、LNMP架构的优点 二、编译安装nginx软件 1、准备工作 1.1 关闭防火墙 1.2 安装依赖包 1.3 创建运行nginx用户 1.4 压缩包解压 2、编译与安装 3、添加nginx自启动文件 三、编译安装mysql软件 1、准备工作 1.1 安装mysq…

利用R语言进行聚类分析实战(数据+代码+可视化+详细分析)

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

width:100%和width:auto有啥区别

项目中使用了with属性&#xff0c;突然好奇auto 和 100% 的区别&#xff0c;特地搜索实践总结了一下观点 一、 width属性介绍二、 代码带入三、 分析比较四、 总结 一、 width属性介绍 width 属性用于设置元素的宽度。width 默认设置内容区域的宽度&#xff0c;但如果 box-siz…

Vue3切换路由白屏刷新后才显示页面内容

1.首先检查页面路由以及页面路径配置是否配置错误。 在router-view 中给路由添加key标识。 &#xff01;&#xff01;注意&#xff1a;有使用layout封装布局的&#xff0c;是在layout下的主页面中的 router-view 添加标识&#xff0c;不是在src根目录下main.vue中修改&#xf…