当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 学习笔记 > Linux内核驱动的platform机制

Linux内核驱动的platform机制 时间:2018-07-26      来源:未知

1.模块(一种特殊的内核代码写法,一般编译成ko文件,用于承载用户想要动态添加进内核的代码(不限于驱动))

a.写法

module_init(模块构造函数 );

module_init(模块析构函数 );

b.编译

标准的Makefile

c.模块相关工具

insmod/rmmod/lsmod/modinfo/modprobe/depmod

为了自动安装有依赖关系的模块,两个前提: 1.模块必须都拷贝到/lib/modules/3.14.0; 2.执行depmod

2.字符设备驱动框架

1.认知

a. 无系统编程(裸机编程.bin,hex)--有系统编程(安全,并发,丰富的驱动。。。elf,exe)

b. OS管理了所有驱动,而且各个操作系统管理结构(数据结构)不一定一样

c. 了解数据结构的意义

d. 回掉

e. 计算机喜欢数字而不是字符串

2.名词

设备文件: 一个特殊的文件用于抽象设备操作入口,用与隐藏设备号细节(域名-IP)

设备号:设备驱动的代号,主设备号 次设备号

驱动:让硬件工作起来的软件(裸机驱动 系统之下的驱动)

驱动框架:平台(操作系统)对驱动编写的要求

3.涉及的函数

申请设备号:

强制申请int register_chrdev_region(dev_t first, unsigned int count, char *name)

动态申请int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)//name设备号说明信息(/proc/devices)

释放设备号:

void unregister_chrdev_region(dev_t first, unsigned int count);

初始化cdev:

void cdev_init(struct cdev *, const struct file_operations *);

注册cdev:

int cdev_add(struct cdev *, dev_t, unsigned);

移除cdev:

void cdev_del(struct cdev *);

1.长得像驱动

struct cdev myled{

.dev = 250

.fops{

.open = led_on;

.release = led_off;

}

};

2.放到内核中去

写到module.c

3.加入内核管理驱动的数据结构

cdev_add(&myled, 250, 1);

cdev_del(&myled);

1.内核希望你写驱动的时候采用总线、设备、驱动分离的方式来写,而为了分离没有具体(I2C,SPI,USB...)总线的设备发明了一个虚拟的platform_bus总线

a.platform_device: 注册设备必要的资源(基地址,引脚,中断号,波特率,ip,精度。。。)信息

b.platform_driver:实现设备操作做的算法(不包含具体数据,必须先匹配再获取);

1. Linux系统中以模块方式组织设备驱动程序,请列举在一个模块程序中必不可少的组成部分。 (可以写个Hello world模块的程序)__init __exit

2. 请说明一下从零创建一个linux字符设备驱动的步骤?

4. 简述Linux设备驱动中使用中断的步骤。

5. 简述信号量和自旋锁的异同和使用时的注意事项。

6. 简述命令 mknod /dev/zero c 1 5 的做用和命令各个部分的含义,并写出创建一个块设备节点的命令(把c改成b)。

7. 简述命令insmod,rmmod,lsmod,depmod,modprobe 的功能。

8. 简述platform设备基本原理, platform设备最大优势是什么?

9. 简述设备驱动程序和普通应用程序的异同点。

10. 简述mmap机制的作用和使用mmap的好处。

1. #include

#include

#include

static int hello_init(void)

{

printk(KERN_ALERT "Hello world enter!\n");

return 0;

}

static void hello_exit(void)

{

printk(KERN_ ALERT " Hello world exit!\n");

}

module_init(hello_init);

module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");

2.

使用alloc_...方法动态注册设备号;

为cdev申请内存;

初始化设备并添加该设备;

完成file_operations中的相应函数功能;

4. request_irq,申请irq;

free_irq,释放irq。

5. 信号量和自旋锁都是解决互斥问题的基本手段,信号量的实现依赖于自旋锁。使用信号量机制时,进程若不能获得信号量,进程不会如自旋锁那样原地打转,而是让进程进入休眠等待状态。当使用信号量的开销时间T1大于使用自旋锁的开销T2时,宜使用自旋锁,若T2大于T1,则宜使用信号量。由于信号量所保护的临界区可能包含引起阻塞的代码,而自旋锁则绝对要避免用来保护这样的代码。信号量存在于进程上下文,而如果被保护的资源需要在中断或者软中断情况下使用,则只能选择自旋锁。

6. mknod,该命令用于创建设备节点。/dev/zero 表示设备节点创建的目录和名字,c 代表创建的设备节点为字符设备节点,1 代表主设备号,5 代表此设备号。

创建块设备节点的命令:mknod /dev/blockdev b 253 0

7.insmod:加载驱动模块到内核;

Rmmod:从内核删除驱动模块;

Lsmod:查看当前内核包含哪些模块

8.原理:

第一:定义一个platform_driver结构体,对probe和remove函数指针进行初始化,对driver里面的成员.owner,.name进行初始化;

第二:在模块的初始化函数中调用platform_drive_registe()初始化这个驱动,在卸载模块中调用platfrom_driver_unregister()注销这个驱动;

第三:将驱动中实用的设备资源信息通过传递进来的platform_device结构体指针获取。

第四:平台设备添加,一种是:用platform_device手动编码;另一种是在设备树中添加一个节点。

匹配过程:一种是:如果是平台设备与平台驱动的匹配以名字匹配,平台总线将会遍历

对方,如果名字相同,则调用平台驱动的probe函数,并且将匹配上的平台设备的结构体指针传给设备函数;另一种是:去匹配设备树中的设备节点里面的兼容属性的值,配上则调用平台驱动的probe函数,并且将匹配上的平台设备的结构体指针传给设备函数。

优势:

platform机制将本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过platform_device提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性

9.异同点:

驱动运行于内核,应用程序再用户空间;应用程序能调用C库;应用程序顺序执行,驱动被动的接受调用;应用程序的栈很大,驱动很小,通常4K;应用程序可以做浮点运算,驱动中很少做浮点运算。

10. 原理:mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。

作用:让用户程序直接访问设备内存,在要求高性能的应用当中比较常用。应用程序使用的动态库映射到这个区域;应用程序调用mmap,将设备物理地址和这个区域的虚拟内存进行映射;

上一篇:变量存储类型 动态内存分配详解

下一篇:树的基本概念

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部