驱动学习-日常笔记day9

【1】复习
platform总线

设备端
	设备信息结构体:
	struct resource res[] = {
		[0] = {
			.start = 0xc0053000,
			.end   = 0xc0053000 + 24 -1,
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = 73,
			.end   = 73,
			.flags = IORESOURCE_IRQ,
		}
	};
	struct platform_device pdev = {
		.name = "hello",
		.id   = -1,
		.dev  = {
			.release = pdev_release,
		},
		.number_resource = 2,
		.resource = res,
	};
	platform_device_register(&pdev);
	platform_device_unregister(&pdev);

驱动端
	struct platform_driver  pdrv = {
		.probe = pdrv_probe,
		.remove = pdrv_remove,
		.driver = {
			.name = "hello",
		},
		.id_table = pdrv_idtable,
	};
	
	platform_driver_register(&pdrv);
	platform_driver_unregister(&pdrv);

【2】i2c的驱动框架
user:
open read write close

kernel
设备驱动层:当总线驱动和设备驱动匹配成功之后执行这里的probe函数
1.注册字符设备驱动,给应用层提供访问的接口
2.封装数据,发送数据(i2c_read_reg,i2c_write_reg)
3.完成硬件(mma8451q)的初始化
-------------------------------------------------------------
核心层(i2c-core.c ):它是由linux内核工程师实现的,提供总线驱
动和设备驱动的注册和注销的方式,以及匹配的过程。
-------------------------------------------------------------
总线驱动层(控制器驱动层):在linux内核中厂商已经将控制器驱动
drivers/i2c/busses|编写好了,对控制器的初始化,数据的发送和接收。
i2c-s3c241.c |
------------------|-----------------------------------------------
hardware : i2c控制器 mma8451q
------------ scl ------------
| |-------------------| x |
| | sda | y |
| |-------------------| z |
| | | |
------------ ------------

 // s3c2410  s3c6410  s5pv210   exynos4412   s5p6818

【3】i2c设备驱动的实现
1.分配的对象
struct i2c_driver {
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
struct device_driver driver;
const struct i2c_device_id *id_table;
};

	struct i2c_driver mma8451q;
2.初始化对象
	mma8451q.probe = mma8451q_probe //匹配成功后执行的函数
	mma8451q.remove = mma8451q_remove//分离执行的函数
	mma8451q.driver.name = "名字"   //这个名字不能用于匹配,但是还必须初始化。
									// /sys/bus/i2c/drivers/2-001c 
	mma8451q.id_table = mma8451q_idtable //用于匹配
	
3.注册
	i2c_add_driver(&mma8451q);

4.注销
	i2c_del_driver(&mma8451q);


一键注册、注销
	module_i2c_driver(mma8451q);

【4】i2c控制器驱动名字的提交
struct i2c_board_info {
char type[I2C_NAME_SIZE]; //提交的名字
unsigned short addr; //从机地址
};

int i2c_register_board_info(int busnum,
	struct i2c_board_info const *info, unsigned len)
功能:向控制器提交名字
参数:
	@busnum :总线号(它和控制器的序号一一对应) 2
	@info   :被提交的信息
	@len    :提交的i2c_board_info的个数
返回值:成功返回0,失败返回错误码	


通用存放设备信息的文件:
arch/arm/plat-s5p6818/fs6818$ vi device.c
 716 /*-----------------------------------------
 717  * G-Sensor platform device
 718  */
 719 #include <linux/i2c.h>
 720 
 721 static struct i2c_board_info mma8451q = {                                                     
 722         .type   = "mma8451q",
 723         .addr   = 0x1c,
 724 };

1905 #elif defined(CONFIG_SENSORS_MMA8451) || defined(CONFIG_MXC_MMA8451_MODULE)
1906     printk("plat: add g-sensor mma8451\n");
-1907   //      i2c_register_board_info(2, &mma8451_i2c_bdi, 1);
1908 #endif
+1909      i2c_register_board_info(2, &mma8451q, 1);  

make uImage  编译内核
cp  arch/arm/boot/uImage ~/tftpboot/  拷贝
重启开发板 

【5】i2c数据的封装和发送的过程
//https://www.cnblogs.com/aspirs/p/12371237.html
//7位 10位从机地址的访问问题
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address /
#define I2C_M_RD 0x0001 /
read data, from slave to master */

struct i2c_msg {
	__u16 addr;	  //从机地址
	__u16 flags;  //读写的标志位 0写 I2C_M_RD读
	__u16 len;	  //本次你要写的数据的长度
	__u8 *buf;	  //消息的首地址
};

*/有多少个起始位就有多少个消息,消息的长度是以字节来表示的 /*

写的消息的封装:
	char w_buf[] = {reg,data};
	struct i2c_msg w_msg = {
		.addr  = client->addr,
		.flags = 0,
		.len   = 2,
		.buf   = w_buf,
	};
	
读的消息的封装:
	char data;
	char r_buf []= {reg};
	struct i2c_msg r_msg[] = {
		[0] = {
			.addr  = client->addr,
			.flags = 0,
			.len   = 1,
			.buf   = r_buf,
		},
		[1] = {
			.addr  = client->addr,
			.flags = I2C_M_RD,
			.len   = 1,
			.buf   = &data,
		},
	};

消息发送:
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
功能:消息的发送函数
参数:
	@adap :总线驱动的对象  client->adapter
	@msgs :消息结构体指针
	@num  :消息的个数
返回值:成功返回发送了的消息的格式,
		否者不是发送的消息的个数。

【6】i2c_client结构体
当设备驱动i2c_driver和总线驱动i2c_adapter匹配成功之后
在内核中就会创建一个i2c_client的结构体,这个结构体就是
用来保存匹配成功后的信息的。
struct i2c_client {
unsigned short addr; //从机地址
char name[I2C_NAME_SIZE];//名字
struct i2c_adapter *adapter;//匹配成功的总线驱动的对象
struct i2c_driver *driver; //匹配成功的驱动端的对象
};


【1】块设备
比如一个移动硬盘:
磁头:有多少个盘面
磁道:一个面内有多少环
扇区:一个环内有多少个扇区,一个扇区512字节

磁盘的数据的读取:
磁盘数据的读取不会按照存储顺序来读取,因为磁头它是机械结构,
通过旋转来访问数据,如果按照数据来访问,需要反复的切换这个
物理结构,比较浪费时间。所以磁盘在访问的时候采用电梯优化的算法
来完成。即一次将一个盘面上的数据全部读取到,然后切换物理结构,
在读取下面的数据。将所有的数据读取完之后,进行数据的排序,排序
之后进行操作。

猜你喜欢

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