驱动学习-日常笔记day8

【1】复习
1.中断
request_irq(irqno,中断处理函数,中断触发方式,名字,传递的参数);
free_irq(irqno,传递的参数);

2.内核定时
	struct timer_list mytimer;
	mytimer.expires = jiffies + HZ; (1s)  //# define HZ CONFIG_HZ	
	mytimer.function = timer_function;  //当定时时间到了会执行
	mytimer.data = 0; //一般用于传递下一次的定时的时间
	init_timer(&mytimer);
	add_timer(&mytimer); //启动定时器,并只会执行一次
	mod_timer(&mytimer,下一次定时的时间);再次启动定时器
	del_timer(&mytimer);

3.gpio子系统
	gpio_request(gpio,NULL);
	gpio_direction_input(gpio);
	gpio_driection_output(gpio,value);
	gpio_set_value(gpio,value);
	gpio_get_value(gpio);
	gpio_free(gpio);
	
4.中断底半部
	软中断,tasklet ,工作队列
	
	tasklet:
		struct tasklet_struct tasklet;
		tasklet_init(&tasklet,tasklet底半部处理函数,传递的参数);
		tasklet_schedule(struct tasklet_struct *tasklet)
		
	工作队列:	
		struct work_struct work;
		INIT_WORK(&work, 工作队列的底半部处理函数);
		schedule_work(&work); 
			
作业:	
	1.编写ADC的驱动(使用中断)

【2】控制器的软中断号的获取方式
find -name irqs.h

	./arch/arm/mach-s5p6818/include/mach/irqs.h
	#include "s5p6818_irq.h"        

	find -name s5p6818_irq.h
	./arch/arm/mach-s5p6818/include/mach/s5p6818_irq.h

	#define IRQ_PHY_ADC   (41 + 32)  //ADC的软中断号

【3】platform总线驱动
platform:就是将设备信息和设备驱动分离,实现这个设备驱动通用。
设备信息和设备驱动通过platform bus完成匹配的过程。通过设备信息
和设备驱动中的名字匹配,当匹配成功之后设备信息端就会携带着信息
到设备驱动中,并执行设备驱动中的probe函数,在probe函数中操作硬件
即可。当设备信息和设备驱动分离的时候执行驱动中的remove函数。

----------------------------------------------------   
				|                |
设备信息端      | platform总线端 |设备驱动端
驱动工程师实现的|内核工程师实现的|驱动工程师实现的
				|                |
----------------------------------------------------

设备信息端 : 
	
	1.分配对象
	struct platform_device {
		const char	* name;
		int		id;
		struct device	dev;
		u32		num_resources;
		struct resource	* resource;
	};
	struct platform_device  pdev;
	2.对象的初始化
		pdev.name  名字,用户匹配
		pdev.id    -1,platform是内核制作出来的,没有真实的硬件存在,填写-1(序号)
		pdev.num_resources 资源的个数
		pdev.resource  描述的资源
		
		struct resource {     //设备信息结构体                                                                              
			resource_size_t start; //起始的资源,需要填写
			resource_size_t end;   //结束的资源,需要填写
			const char *name;      //名字
			unsigned long flags;   //资源的类型,需要填写
			struct resource *parent, *sibling, *child; //内核链表
		};

		#define IORESOURCE_IO	0x00000100  IO口资源
		#define IORESOURCE_MEM	0x00000200  内存资源
		#define IORESOURCE_IRQ	0x00000400  中断资源
		#define IORESOURCE_DMA	0x00000800  DMA资源
		
		pdev.dev.release =  释放资源的函数、如果不写卸载驱动的时候会崩溃
		void	(*release)(struct device *dev);
		
	3.对象的注册
		int platform_device_register(struct platform_device *pdev);
	4.对象注销
		void platform_device_unregister(struct platform_device *pdev)
		
		
		
设备驱动端 :
	1.分配对象
	struct platform_driver {
		int (*probe)(struct platform_device *);
		int (*remove)(struct platform_device *);
		struct device_driver driver;
		const struct platform_device_id *id_table;
	};
	struct platform_driver pdrv;
	
	2.对象的初始化
		pdrv.probe=pdrv_probe //匹配成功执行的函数
		pdrv.remove = pdrv_remove //分离的时候执行的函数
		pdrv.driver.name          //1.用于匹配的名字
		pdrv.id_table             //2.用于匹配的
		//pdrv.driver.of_match_table//3.设备树匹配
		
		
	3.对象的注册
		platform_driver_register(&pdrv);
		
	4.对象注销	
		platform_driver_unregister(&pdrv);

【4】在驱动端获取设备信息的函数
struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num)
功能:在驱动端获取设备信息
参数:
@dev :设备端的对象的指针
@type :资源的类型
@num :同类资源中的第几个,每种资源都是从0开始的。
返回值:成功返回struct resource *的结构体指针
失败返回NULL

int platform_get_irq(struct platform_device *dev, unsigned int num)
功能:获取中断资源
参数:
@dev :设备端的对象的指针
@num :中断资源中的第几个,每种资源都是从0开始的。
返回值:成功返回中断号,失败返回错误码

【5】id_table的匹配方式
struct platform_device_id {
char name[PLATFORM_NAME_SIZE]; //用于匹配的名字
kernel_ulong_t driver_data //传递的数据,如果不关心0
};

struct platform_device_id pdrv_idtable[] = {
	{"hello_adc",},
	{"hello_adc0",},	
	{"hello_adc1",},
	{"hello_adc2",},
	{/*结束*/},  //如果不写这个空的花括号,内核在比较名字的时候
};               //有可以会一直循环着比较,如果碰巧匹配上了有可能导致内核崩溃

如果驱动中既有idtable又有名字,匹配的优先级是先匹配idtale如果idtable
没有匹配上然后去匹配名字。

【6】module_platform_driver功能
#define module_platform_driver(pdrv)
module_driver(pdrv, platform_driver_register,platform_driver_unregister)

#define module_driver(__driver, __register, __unregister, …)

static int __init pdrv_init(void)
{
return platform_driver_register(&pdrv);
}
module_init(pdrv_init);
static void __exit pdrv_exit(void)
{
platform_driver_unregister(&pdrv);
}
module_exit(pdrv_exit);

【7】i2c硬件知识回顾
1.几根线
scl :时钟线
sda :数据线
2.几种信号
起始信号:
在scl为高电平的时候,sda从高到低的跳变
停止信号:
在scl为高电平的时候,sda从低到高的跳变
应答信号:
sda为低电平
3.两种时序
写时序:
start +7bit从机地址(0写)+ack+reg(8bit)+ack+data+ack+stop

	读时序:
		start +7bit从机地址(0写)+ack+reg(8bit)+ack+
		start +7bit从机地址(1读)+ack+从机给主机反馈data+NO ack+stop

4.i2c传输速率
	100K   400K   3.4M

猜你喜欢

转载自blog.csdn.net/weixin_48430195/article/details/108671837
今日推荐