一、驱动认知

首先理解Linux内核框图
文件系统认知,Linux内核框图

1、什么是驱动

  1. linux内核驱动。软件层面上的驱动 广义上是指:这一段代码操作了硬件去动,所以这一段代码就叫硬件的驱动程序。
  2. 狭义上驱动程序就是专指操作系统中用来操控硬件的逻辑方法的部分代码。而我们这里讲的驱动就指的是这个狭义上的驱动。

2、Linux驱动的体系架构

  1. 分离、分层思想
  2. 驱动的上面是系统调用API
  3. 驱动的下面是硬件
  4. 驱动本身的实现也是基于分离、分层的思想(比如分成不同类型的驱动)

3、Linux驱动的分类

  1. 分3类:字符设备驱动、块设备驱动、网络设备驱动
  2. 分类原则:设备本身读写操作的特征差异
  3. 时刻要注意一点,我们的驱动本质上是不分类的,因为我们的硬件是不同的,有不同的读写特性,所以的硬件是分类的,所以我们的驱动也就要跟着分类了

字符设备:准确的说应该叫“字节设备”,软件操作设备时是以字节为单位进行的。典型的如LCD、串口、GPIO、蜂鸣器、触摸屏······
块设备:块设备是相对于字符设备定义的,块设备被软件操作时是以块(多个字节构成的一个单位)为单位的。设备的块大小是设备本身设计时定义好的,软件是不能去更改的,不同设备的块大小可以不一样。常见的块设备都是存储类设备,如:硬盘、NandFlash、iNand、SD····操作块设备时,我们必须以块单位进行操作,将一块的数据读取到内存中去,然后在内存中找到相应的那个字节数据修改之后再以一块的数据写入到我们的块设备中去
网络设备:网络设备是专为网卡设计的驱动模型,linux中网络设备驱动主要目的是为了支持API中socket相关的那些函数工作

4.为什么要学习写驱动

  1. 树莓派开发简单是因为有厂家提供的wiringPi库,实现超声波,实现继电器操作,做灯的点亮…都非常简单
  2. 但未来做开发时,不一定都是用树莓派,则可能没有wiringPi库可以用。但只要能运行Linux系统,linux的标准C库一定有
  3. 所以我们可以基于C库、Linux内核和拿到芯片手册,电路图…就能做开发,写一套属于自己的驱动库

二、开始树莓派Linux内核驱动开发

  1. 设备驱动文件路径:/home/pi/lessonPI/linux-rpi-4.14.y/drivers,在Linux环境编写
  2. 设备文件(文件显示黄色)路径:根目录下的dev文件/dev,在树莓派环境使用
  3. 在Linux环境通过写好设备驱动文件然后进行内核编译生成驱动模块xxx.ko,接着把驱动模块发送给树莓派,树莓派把驱动模块加载到设备文件。从而用户可以通过/dev目录下的这些设备文件访问外部硬件设备,比如通过open(/dev/mouse,O_RDONLY)来访问鼠标的输入 从而可以进行各种骚操作
  4. 内核底层其实是用链表去管理这些驱动,学过FreeRTOS系统源码的可以从FreeRTOS源码的底层链表去理解
  5. 设备驱动文件需要有设备号、主设备号、次设备号、设备文件名。这些可以理解为驱动任务节点所需要的内容,可以从FreeRTOS源码的任务节点去结合这个理解
  6. 整个过程大致:C库open——>sys_call——>sys_open(属于VFS层虚拟文件系统)——>根据open里的那个设备文件里的设备名去内核找到驱动链表——>接着根据其主设备号与次设备号找到相关驱动函数,所以我们只需要让内核执行我们自己写的设备名(即执行我们最后得到的设备文件),就可以执行我们写的驱动函数了
  1. 拷贝设备驱动文件代码
    gpio属于字符设备,所以把该设备驱动文件拷贝到/home/pi/lessonPI/linux-rpi-4.14.y/drivers/char
#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  devise声明
#include <linux/uaccess.h>
#include <linux/types.h> //设备号  dev_t 类型声明
#include <asm/io.h>  //ioremap iounmap的头文件static struct class *pin4_class;
static struct device *pin4_class_dev;static dev_t devno;          //设备号
static int major = 232;      //主设备号
static int minor = 0;        //次设备号
static char *module_name = "pin4"; //设备文件名//.open = pin4_open,所以执行open(fd,O_RDWR)时会进入此函数
static int pin4_open(struct inode *inode, struct file *file)
{printk("pin4_open\n"); //内核的打印函数和printf类似return 0;
}//.write= pin4_write,所以执行write(fd,'1',1)时会进入此函数
static ssize_t pin4_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{printk("pin4_write\n"); //内核的打印函数和printf类似return 0;
}//内核链表里的结构体相关配置
static struct file_operations pin4_fops =
{.owner = THIS_MODULE,.open = pin4_open,.write = pin4_write,
};//入口函数
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");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");
  1. 拷贝用户层应用代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>int main()
{int fd;fd = open("/dev/pin4",O_RDWR); //调用C库open,执行我们做好的设备文件pin4,因为我们把.open=pin4_open,所以会运行pin4_open函数if(fd < 0){printf("open failed\n");perror("reson");}else{printf("open success\n");}write(fd,"a",strlen("a")); //调用C库wirte,因为我们把.wrute=pin4_write,所以会运行pin4_write函数close(fd);return 0;
}
  1. 在/drivers/char目录下修改Makefile配置文件,打开后加入obj-m += pin4driver.o,为了进行内核编译时能把设备驱动文件生成为驱动模块xxx.ko
  2. 在Linux里回到树莓派内核源码根目录linux-rpi-4.14.y,执行指令进行编译内核:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules
    补充:modules:我们只需生成驱动模块,所以只需modules参数即可

    编译成功,生成pin4driver.ko驱动模块
    编译完成后执行指令发送给树莓派scp drivers/char/pin4driver.ko pi@192.168.1.1:/home/pi
  3. 执行指令编译应用代码:arm-linux-gnueabihf-gcc pin4text.c -o pin4text
    编译完成后执行指令发送给树莓派scp pin4text pi@192.168.1.1:/home/pi
  4. Linux操作完了,接下来到树莓派操作了。
    执行指令加载到设备文件(即把pin4driver.ko驱动模块加载到/dev设备文件里)sudo insmod pin4driver.ko
  5. 查看加入后的设备号是否和代码写的一样ls pin4 -l,可见主设备号和次设备号和代码里的一样

    执行lsmod查看是否有pin4driver驱动模块

    若一样和有说明以上操作成功了
  6. 还需要给pin4这个设备文件一个权限,执行指令:sudo chmod 666 /dev/pin4
    补充:666代表所有人都可以读写pin4
  7. 运行用户代码./pin4text,运行完成后输入指令查看运行完./pin4text后内核打印了什么dmesg | grep pin4

    可见,确实是按照我们写好的设备驱动文件打印。
    到此,你已经实现了调用自己的设备文件了,然后就可以进行各种骚操作啦

回顾:第二大点灰色款里的第3小点,用户可以通过/dev目录下的这些设备文件访问外部硬件设备,所以我们需要学会这套技能

转载请标明出处,谢谢
作者:星辰~念

树莓派基于Linux内核驱动开发详解相关推荐

  1. 树莓派基于Linux内核驱动开发

    一.驱动认知 1.1 为什么要学习写驱动 树莓派开发简单是因为有厂家提供的wiringPi库,实现超声波,实现继电器操作,做灯的点亮-都非常简单. 但未来做开发时,不一定都是用树莓派,则没有wirin ...

  2. 第三阶段:43-47.树莓派基于Linux内核驱动开发

    目录 一.驱动认知 1.1 为什么要学习写驱动 1.2 文件名与设备号 1.3 open函数打通上层到底层硬件的详细过程 二.基于框架编写驱动代码 2.1 编写上层应用代码 2.2 修改内核驱动框架代 ...

  3. Linux设备驱动开发详解 第3版 (即 Linux设备驱动开发详解 基于最新的Linux 4 0内核 )前言

    Linux从未停歇脚步.Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核.做技术,从来没有终南捷径,拼的就是坐冷板凳的 ...

  4. 《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)网购链接

    <Linux设备驱动开发详解:基于最新的Linux 4.0内核> china-pub   天猫     dangdang   京东 China-pub 8月新书销售榜 推荐序一 技术日新月 ...

  5. 《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)进展同步更新

    本博实时更新<Linux设备驱动开发详解(第3版)>的最新进展. 目前已经完成稿件. 2015年8月9日,china-pub开始上线预售: http://product.china-pub ...

  6. 《Linux 设备驱动开发详解(第2版)》——1.4 Linux设备驱动

    本节书摘来自异步社区<Linux 设备驱动开发详解(第2版)>一书中的第1章,第1.1节,作者:宋宝华著,更多章节内容可以访问云栖社区"异步社区"公众号查看 1.4 L ...

  7. 《Linux设备驱动开发详解(第2版)》隆重出版

    Linux设备驱动开发详解(第2版)(前一版狂销3万册,畅销书最新升级) [新品] 点击看大图     基本信息 * 作者: 宋宝华       * 出版社:人民邮电出版社     * ISBN:97 ...

  8. linux设备驱动开发详解孔夫子,Linux设备驱动开发详解

    [内容简介] <Linux设备驱动开发详解(第2版)>是一本介绍linux设备驱动开发理论.框架与实例的书,<Linux设备驱动开发详解(第2版)>基于ldd6410开发板,以 ...

  9. 《Linux设备驱动开发详解 A》一一2.3 接口与总线

    本节书摘来华章计算机出版社<Linux设备驱动开发详解 A>一书中的第2章,第2.3节,作者:宋宝华 更多章节内容可以访问云栖社区"华章计算机"公众号查看.1 2.3 ...

最新文章

  1. 机器学习01-定义、线性回归、梯度下降
  2. react: menuService
  3. 不吹不黑,中美程序员的区别对比!
  4. 2PC协议(2-phase-commit protocol)
  5. Chapter1-5_Speech_Recognition(Alignment of HMM, CTC and RNN-T)
  6. kafka 如何做到1秒发布百万级条消息?
  7. python如何定义i_如何在Python中使用自定义消息引发相同的Exception?
  8. springboot整合rabbitMQ-路由模型
  9. python下载显示文件丢失_python27.dll是什么文件|python27.dll丢失修复下载32/64位
  10. ndoutils2.2.0(ndo2db)中文乱码问题解决
  11. Tkinter(二) | 点击按钮显示图片
  12. 多模态机器学习概述及其音视频融合总结
  13. thinkphp创建临时表
  14. Visual Studio 2017 Intro
  15. Linux全面解析讲解
  16. 英国脱欧对中国光伏产业的短期及长期影响
  17. dotcms open source java cms,开源Java CMS
  18. java am pm_java – 如何以AM / PM格式显示时间
  19. PHP设计模式(一)
  20. 【获取数据表格(datagrid)中编辑器(editor)的值】

热门文章

  1. Macromedia的历史
  2. jvm万字总结(图文+代码示例)
  3. 木瓜得了肿瘤病,是缺硼了,看看如何治疗
  4. 阳阳买苹果,每个苹果0.8元,阳阳第一天买两个苹果,第二天开始每天买前一天的两倍, 直到购买的苹果个数为不超过100的最大值, 求阳阳每天平均花多少钱?
  5. 简单的均线突破交易系统
  6. 为什么会得肺癌,得了肺癌怎么治?
  7. 实现京东商品详情页面的商品切换功能
  8. modelsim do文件简介及仿真波形分析注意事项
  9. 华南理工大学计算机系就业率,21考研择校:华南理工大学就业率和薪酬情况统计!...
  10. 关于Android集成高德地图的那些事儿...显示地图