字符驱动

参考: https://www.bilibili.com/video/av51099369?p=10

内核驱动

硬件 -》 驱动 -》 内核子系统(进程管理、内存管理、文件系统、设备控制、网络) -》系统调用

驱动的类型

  1. 字符设备驱动
  2. 块设备驱动
  3. 网络设备驱动

驱动的静态加载和动态加载

动态加载M选项,生成ko文件

区别

  • 编译选项(编写进内核还是编写为驱动)
  • 存在位置(驱动代码在内核镜像还是文件系统内)
  • 加载时机

优势

  • 热插拔
  • 驱动调试
  • 开机优化

字符设备驱动

相关概念

设备号

**dev_t **
实质是unsigned int 32位整数,高12位为主设备号(区分不同类别的设备)、低20位为次设备号(同类设备的多个设备)。

注册设备号int register_chrdev_region(dev_t from, unsigned count, const char *name)

设备信息的描述

struct cdev{
	struct kobject kobj;
    struct module *owner;
    const struct file_operations *ops;
    struct list_head list;
    dev_t dev;
    unsigned count;	//已支持的设备
}

设备行为的描述

struct file_operations{
	struct module *owner;
    ...
	ssize_t (*read)(struct file*, char __user*, size_t, loff_t *);
    ssize_t (*write)(struct file*, const char __user*, size_t, loff_t *);
    int (*open)(struct inode*, struct file*);
    int (*release)(struct inode *, struct file*);
    ...
}

相关注册函数

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

方便内核统一管理

内核驱动源码

4次关联,5层结构:自定义函数(设备行为,如read、write、open) -> file_operations -> struct cdev -> 设备号 -> 设备文件(/dev/..)

int charDrvInit(void)
{
        devNum = MKDEV(reg_major, reg_minor);

if( OK == register_chrdev_region(devNum, subDevNum, "testchar")){
printk(KERN_EMERG"register_chrdev_region ok\r\n");
}
else{
printk(KERN_EMERG"register_chrdev_region error ok\r\n");
return ERROR;
}

gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);

        gFile->open = testOpen;
        gFile->read = testRead;
        gFile->write = testWrite;
        gFile->owner = THIS_MODULE;

        cdev_init( gDev, gFile);
        cdev_add( gDev, devNum, 3);

        return 0;
}

void __exit charDevExit( void )
{
        cdev_del(gDev);
        unregister_chrdev_region( devNum, subDevNum);
        return;
}

module_init( charDrvInit );
module_exit( charDevExit );

MODULE_LICENSE( "GPL" );

内核编译系统原理

make menuconfig

图形化配置,实质是遍历并显示所有目录下的kconfig文件。

tristate: 3种选择 y(编译进内核)/n/m

config MINI210_BUTTONS
	tristate
	depends on CPU_55PV210
	default y
	help
		this is button ...

ID值:CONFIG_MINI210_BUTTONS = y/n/m

.config: 最终配置

make实质

遍历所有目录下的makefile,并且按照makefile的内容编译相关代码

onj-$(CONFIG_MINI210_BUTTONS) += mini210_button.o
obj-y: 编译进内核
obj-m: 编译为驱动

操作

  1. 在linux-2.6.32.2/drivers/char/Kconfig为charDev添加一个config条目。比如TEST_CHAR
  2. 修改linux-2.6.32.2/drivers/char/Makefile, 添加代码
    obj-$(CONFIG_TEST_CHAR) += charDev.o
  3. 把charDev.c拷贝到linux-2.6.32.2/drivers/char/下
  4. make munuconfig, 选中CONFIG_TEST_CHAR项目,设为M或者Y
  5. 重新编译

驱动中断

定时器

posted @ 2020-03-01 16:19  friedCoder  阅读(240)  评论(0)    收藏  举报