IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 树莓派基于Linux内核驱动开发详解 -> 正文阅读

[系统运维]树莓派基于Linux内核驱动开发详解

一、驱动认知

首先理解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目录下的这些设备文件访问外部硬件设备,所以我们需要学会这套技能

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

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-24 15:57:18  更:2021-08-24 16:02:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 11:44:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码