一、使用字符设备驱动
1、编译驱动、安装;创建设备文件;访问设备
2、设备描述结构cdev:结构定义;设备号dev_t;设备操作集
3、驱动初始化:分配设备描述结构;初始化设备描述结构;注册设备描述结构
4、设备号为unsigned int;MKDEV;MAJOR;MINOR
5、动态分配主设备号:alloc_chrdev_region;驱动退出时:unregister_chrdev_region
6、描述结构的分配:静态struct cdev mdev;动态cdev_alloc()
7、描述结构的初始化:cdev_init
8、描述结构的注册:cdev_add()
9、驱动注销:cdev_del
二、混杂设备驱动模型
1、拥有相同的主设备号10称为混杂设备
2、设备描述:struct miscdevice
3、注册混杂设备驱动:misc_register()
4、内核中断处理流程:irq_svc入口-->获取中断号-->根据中断号找到相应的irq_desc结构-->取出事先注册好的处理函数运行
5、中断注册:request_irq(unsigned int irq, void (*handler)( ), unsigned long flags, const char *devn ame, void *dev_id)
6、flags:IRQF_DISABLED(SA_INTERRUPT)表示快速中断;IRQF_SHARED(SA_SHIRQ)表明该中断号是多个设备共享的
7、中断注销:free_irq()
8、中断嵌套:当中断发生时,又产生了其他中断
9、中断嵌套的处理方法-->中断分层技术:软中断;tasklet;工作队列
10、工作队列:将下半部分交给内核线程处理
11、描述工作队列:struct workqueue_struct
12、描述一个工作项:struct work_struct13、创建工作队列:create_workqueue
14、创建工作:INIT_WORK
15、提交工作:queue_work
16、提交工作到默认队列:schedule_work
17、内核定时器:struct timer_list
18、初始化定时器:init_timer()、 设置超时函数、
19、注册定时器:add_timer()
20、启动定时器:mod_timer(要启动的定时器,超时时间)
21、当一个进程试图向设备读写数据时,设备暂时没有准备好数据。。驱动程序就应当阻塞进程,进入睡眠状态,直到请求得到满足
22、定义等待队列:wart_queue_head_t my_queue
23、初始化等待队列:init_waitqueue_head(&my_queue)
24、定义+初始化等待队列:DECLARE_WAIT_QUEUE_HEAD(my_queue)
25、进入等待队列,睡眠:wait_event(queue, condition),当condition为真时,立即返回,否则进入TASK_UNINTERRUPTIBLE
26、wait_event_interruptible(queue, condition),当condition为真时,立即返回,否则进入TASK_INTERRUPTIBLE
27、从等待队列中唤醒进程:wake_up() --->可唤醒UNINT*、INT*、KILL*的所有进程
28、wake_up_interruptible(),只能唤醒TASK_INTERRUPTIBLE的进程
三、总线设备驱动
1、总线描述:bus_type
2、总线描述结构中的match函数:当一个新设备或新驱动被添加到这个总线时,调用该函数。判断是否匹配
3、总线的注册:bus_register()
4、总线的注销:bus_unregister()
5、驱动描述结构:device_driver
6、驱动的注册:driver_register()
7、驱动的注销:driver_unregister()
8、设备描述结构:struct device
9、设备的注册:device_register()\
10、设备的注销:device_unregister()
11、平台总线:Platform bus
12、平台设备描述结构:struct platform_device
13、注册平台设备:platform_device_register()
14、平台驱动描述结构:struct platform_driver
15、注册平台驱动:platform_driver_register()
注:16、当device_register注册设备时,dev->name会赋值给dev->kobj.name,自己变为NULL
注:17、先加载总线,后加载驱动或设备