Linux驱动(9)--注册设备
注册设备
- 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)--注册设备相关推荐
- Linux驱动(11)--生成设备节点
生成设备节点 1. 生成设备节点 1.1 杂项设备 1.2 注册文件 1.3 生成设备节点源代码 1.4 生成设备节点步骤 1.5 需要注意的问题 2. 调用设备节点 1. 生成设备节点 1.1 杂项 ...
- 【linux驱动之字符设备驱动基础】
linux驱动之字符设备驱动基础 文章目录 linux驱动之字符设备驱动基础 前言 一.开启驱动学习之路 二.驱动预备知识 三.什么是驱动? 3.1 驱动概念 3.2 linux 体系架构 3.3 模 ...
- linux驱动之字符设备
linux驱动之字符设备 linux驱动设备分类 linux驱动分为了三种驱动: 字符设备: 字符设备和应用程序之间是以字节进行进行数据交换的.在进行数据交换的时候数据是以一定顺序进行传输的,传输是实 ...
- linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...
Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...
- Linux驱动之字符设备驱动
系列文章目录 第一章 Linux入门之驱动框架 第二章 Linux驱动之字符设备驱动 文章目录 系列文章目录 前言 一.认识字符设备驱动 1.基本概念 2.基本概念 二.字符设备旧框架 1.注册和注销 ...
- linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...
原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...
- 【Linux驱动开发】设备树详解(二)设备树语法详解
活动地址:CSDN21天学习挑战赛 [Linux驱动开发]设备树详解(一)设备树基础介绍 [Linux驱动开发]设备树详解(二)设备树语法详解 [Linux驱动开发]设备树详解(三)设备树Kern ...
- linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用
private_data改进 为设备驱动支持多个设备个体做准备,针对private_data进行改进 在设备打开操作中通过inode中保存的i_cdev获取代表当前设备的cdev对象 通过代表当前设备 ...
- 【Linux驱动】字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...
最新文章
- Python:Spider
- joyui版本和android版本,游戏爱好者注意!JOYUI 11来了
- 蚂蚁金服面试经历!临场发挥!
- Ubuntu16.04 安装R与RStudio
- 几个关于money处理的函数
- private 私有的 外部不能访问的
- 装修月记第一弹,硬装篇
- POJ 1753 位运算+枚举
- 计算机丢失lua51dll怎么修复,lua51.dll
- 移动位置应用的推动者——ArcGIS移动产品家族
- 思科OSPF详细配置命令过程
- 如何找到WIN10自带桌面背景图,看这里就够了,系统自带背景图怎么找到存放在哪里
- 通过高阶DMD对地铁的实时短时OD预测
- 远大驾校 考驾照 报名 科目一 科目二 科目三 科目四 视频
- ndows 内存诊断工具,Windows10自带内存检测工具的使用方法
- 鸿蒙1004鸿蒙,第1004章 【两成】
- Linux:VNC桌面锁屏问题处理
- Web(万维网)发展简史
- python for ArcGIS 绘制南京市板块地图
- OpenCV 各版本百度云下载
热门文章
- Spring Data JPA 写SQL语句也可以如此简单
- php 数组相乘,PHP如何计算数组中所有值的乘积?(代码示例)
- 信安教程第二版-第20章数据库系统安全
- 信息安全工程师考试大纲-科目2:信息安全应用技术
- session的简介
- 给button加href
- System.gc()与Object.finalize()的区别
- html(7)盒子模型
- 高级查询(1.连接查询(对列的扩展)2.联合查询(对行的扩展)3.子查询)
- [bbk2907]第3集 - Chapter 02 - RAC的安装过程中需要注意的要点