注册设备

  • 1. 总线设备驱动注册流程
  • 2. 以内核的方式注册设备
  • 3. 以module的方式注册设备
  • 4. 注意

1. 总线设备驱动注册流程

Linux下的总线设备驱动注册流程如下图所示:

① Linux中有很多总线,比如SPI总线、hid总线、media总线等。我们可以用命令:

ls /sys/bus

来观察linux下中的总线设备:

② Linux驱动一般挂载在平台总线上,也就是上图中的platform总线。
③ Linux平台总线挂载这两个链表,一个是设备链表,一个是驱动链表。设备链表用来注册设备,驱动链表用来注册驱动。
④ 注册设备是使用platform_device结构体来进行注册,我们可以利用命令:

ls /sys/devices/platform/

来查看在平台总线上注册的设备,以及利用命令:

cat /proc/devices

来查看设备号。
⑤ 注册驱动是使用platform_driver结构来进行注册。
⑥ 在注册完毕设备和驱动之后,platform总线利用platform_match函数来匹配设备和驱动的name,只有两者的name相同时,驱动才可以正常工作

2. 以内核的方式注册设备

注册设备有两种方式,一种是将设备编译到内核中(常用),一种是将设备编译成module通过外置存储挂载安装(调试用)。首先说一下以内核的方式注册设备。
注册设备使用结构体platform_device,该结构体在头文件:

/LinuxKernelPath/include/linux/platform_device.h

中,头文件也同样包含了注册设备和卸载设备的函数:

以内核的方式注册我们只需要用到结构体中的name和id参数即可。在内核中注册设备只需要将设备写进平台文件中即可。本文用到的平台是ARM平台,平台文件在路径:

/LinuxKernelPath/arch/arm/mach-exynos/match-itop4412.c

我们需要添加两个地方:
Ⅰ 在文件中我们搜索LEDS,可以发现如下所示的结构体:

我们只需要仿照这个结构写我们自己的设备结构体即可,以helloworld为例:

#ifdef CONFIG_HELLOWORLD_CTL
struct platform_device_s3c_helloworld_ctl = {.name = "helloworld_ctl",.id = -1,     //-1表示只有一个设备
};
#endif

添加到平台文件中即可。

Ⅱ 同样再次搜索LEDS,发现如下宏定义:

同样,我们仿照该宏定义,插入自己设备的宏定义,以helloworld为例:

#ifdef CONFIG_HELLOWORLD_CTL&s3c_device_helloworld_ctl,
#endif

添加到平台文件即可,编译内核的时候会自动注册设备。
具体的注册步骤如下所示:
① 注册设备。将设备结构体放到平台文件中,具体步骤如上所示
② 在Kconfig文件中添加编译helloworld设备的宏定义(参考上篇博文)
③ 配置menuconfig中的helloworld宏定义(参考上篇博文)
④ 生成新的zImage(参考上篇博文)

3. 以module的方式注册设备

用module的方式注册设备和用module的方式编译驱动步骤一样,我们需要将设备注册的.c文件写好,与Makefile文件一起编译生成.ko文件,然后在ARM板上装载即可。以module方式注册设备的例程为:

/*
Name:Device_Module.c
Author:Ethan
Version:1.0
Date:2019-11-29
*//*包含初始化宏定义的头文件,代码中的module_init和module_exit再次文件中)*/
#include<linux/init.h>
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
#include<linux/module.h>
/*驱动注册的头文件,包含驱动的结构体以及注册和卸载的函数*/
#include<linux/platform_device.h>/*声明是开源的,没有内核版本限制*/
MODULE_LICENSE("Dual BSD/GPL");
/*声明作者*/
MODULE_AUTHOR("Ethan");static void device_module_release(struct device *dev){/*打印hello world,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello Release! \n");
}/*定义设备结构体*/
struct platform_device device_module = {.name = "my_device_module",.id = -1,.dev = {.release = device_module_release,}
};/*编写初始化函数*/
static int hello_init(void)
{/*定义设备状态变量*/int deviceState;/*打印hello world,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello World! \n");/*注册helloworld驱动*/deviceState = platform_device_register(&device_module);/*打印驱动注册状态,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "deviceState is %d! \n",deviceState);return 0;
}//编写卸载函数
static void hello_exit(void)
{/*打印see you,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "See you!\n");/*卸载helloworld驱动*/platform_device_unregister(&device_module);}/*初始化函数*/
module_init(hello_init);
/*卸载函数*/
module_exit(hello_exit);

相应的Makefile文件为(只更改名字即可):

#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译Device_Module.c这个文件编译成中间文件Device_Module.o
obj-m += Device_Module.o #源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0#当前目录变量
PWD ?= $(shell pwd)#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:make -C $(KDIR) M=$(PWD) modules#make clean执行的操作是删除后缀为o的文件
clean:rm -rf *.o

注册设备的步骤为下:
① 将Device_Module.c和Makefile文件移动到linux系统中的某一文件夹下(任意地方或者新建都可以)。
② 执行命令:

make

执行完毕之后可以在该文件夹下生成.ko文件,该文件就是编译生成的驱动。
③ 我们通过开发板来验证该驱动是否编写与编译成功:
—>将.ko文件拷贝到U盘中
—>用命令

mount /dev/sda1 /mnt/disk/

将U盘挂载。
—>可以用命令

ls /mnt/disk/

来列出已经编译成功的.ko文件
—>用加载命令,来加载我们编译好的驱动

insmod /mnt/disk/Device_Module.ko

加载结果为:


—>用卸载命令,来卸载刚装好的helloworld驱动

rmmod Device_Module

卸载结果为:

4. 注意

① 对于绝大多数情况下,都是以平台文件的方式,在同一的内核文件中来注册设备。
② 注册驱动和注册设备都是将代码潜入到Linux内核中。
③ 无论是在平台文件中注册设备,还是以module的方式注册设备,设备都要优先于驱动注册,否则驱动无法进入prob函数,也就无法进行初始化和工作了。

Linux驱动(9)--注册设备相关推荐

  1. Linux驱动(11)--生成设备节点

    生成设备节点 1. 生成设备节点 1.1 杂项设备 1.2 注册文件 1.3 生成设备节点源代码 1.4 生成设备节点步骤 1.5 需要注意的问题 2. 调用设备节点 1. 生成设备节点 1.1 杂项 ...

  2. 【linux驱动之字符设备驱动基础】

    linux驱动之字符设备驱动基础 文章目录 linux驱动之字符设备驱动基础 前言 一.开启驱动学习之路 二.驱动预备知识 三.什么是驱动? 3.1 驱动概念 3.2 linux 体系架构 3.3 模 ...

  3. linux驱动之字符设备

    linux驱动之字符设备 linux驱动设备分类 linux驱动分为了三种驱动: 字符设备: 字符设备和应用程序之间是以字节进行进行数据交换的.在进行数据交换的时候数据是以一定顺序进行传输的,传输是实 ...

  4. linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...

    Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...

  5. Linux驱动之字符设备驱动

    系列文章目录 第一章 Linux入门之驱动框架 第二章 Linux驱动之字符设备驱动 文章目录 系列文章目录 前言 一.认识字符设备驱动 1.基本概念 2.基本概念 二.字符设备旧框架 1.注册和注销 ...

  6. linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...

    原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...

  7. 【Linux驱动开发】设备树详解(二)设备树语法详解

    ​ 活动地址:CSDN21天学习挑战赛 [Linux驱动开发]设备树详解(一)设备树基础介绍 [Linux驱动开发]设备树详解(二)设备树语法详解 [Linux驱动开发]设备树详解(三)设备树Kern ...

  8. linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用

    private_data改进 为设备驱动支持多个设备个体做准备,针对private_data进行改进 在设备打开操作中通过inode中保存的i_cdev获取代表当前设备的cdev对象 通过代表当前设备 ...

  9. 【Linux驱动】字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...

最新文章

  1. Python:Spider
  2. joyui版本和android版本,游戏爱好者注意!JOYUI 11来了
  3. 蚂蚁金服面试经历!临场发挥!
  4. Ubuntu16.04 安装R与RStudio
  5. 几个关于money处理的函数
  6. private 私有的 外部不能访问的
  7. 装修月记第一弹,硬装篇
  8. POJ 1753 位运算+枚举
  9. 计算机丢失lua51dll怎么修复,lua51.dll
  10. 移动位置应用的推动者——ArcGIS移动产品家族
  11. 思科OSPF详细配置命令过程
  12. 如何找到WIN10自带桌面背景图,看这里就够了,系统自带背景图怎么找到存放在哪里
  13. 通过高阶DMD对地铁的实时短时OD预测
  14. 远大驾校 考驾照 报名 科目一 科目二 科目三 科目四 视频
  15. ndows 内存诊断工具,Windows10自带内存检测工具的使用方法
  16. 鸿蒙1004鸿蒙,第1004章 【两成】
  17. Linux:VNC桌面锁屏问题处理
  18. Web(万维网)发展简史
  19. python for ArcGIS 绘制南京市板块地图
  20. OpenCV 各版本百度云下载

热门文章

  1. Spring Data JPA 写SQL语句也可以如此简单
  2. php 数组相乘,PHP如何计算数组中所有值的乘积?(代码示例)
  3. 信安教程第二版-第20章数据库系统安全
  4. 信息安全工程师考试大纲-科目2:信息安全应用技术
  5. session的简介
  6. 给button加href
  7. System.gc()与Object.finalize()的区别
  8. html(7)盒子模型
  9. 高级查询(1.连接查询(对列的扩展)2.联合查询(对行的扩展)3.子查询)
  10. [bbk2907]第3集 - Chapter 02 - RAC的安装过程中需要注意的要点