Linux驱动开发_平台设备总线、IIC总线、编写触摸屏驱动

举报
DS小龙哥 发表于 2022/04/28 23:57:16 2022/04/28
【摘要】 介绍Linux下平台设备总线框架、完成设备端驱动匹配、介绍IIC子系统框架、完成触摸屏坐标读取。

任务1: 平台设备总线

总线: 可以挂载多个子设备。IIC、SPI……

平台设备总线是虚拟总线----数据结构、链表。

平台设备总线: 有两条线---两条链表 (1.存放设备端资源节点) (2). 驱动端资源节点

一个驱动可以匹配多个设备端的。

平台设备端代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/platform_device.h>

/*资源结构体*/
static struct resource	tiny4412_resource[]=
{
	{
		.start=0x110002E0,
		.end=0x110002E4,
		.name="led_src",
		.flags=IORESOURCE_MEM
	},
	/*继续赋值资源*/
};

static void	tiny4412_dev_release(struct device *dev)
{
	printk("tiny4412_dev_release\n");
}

static u32 data=666;
/*平台设备的设备端端结构体*/
static struct platform_device plat_dev=
{
	.name="tiny4412_platdev",
	.id=1,
	.num_resources=sizeof(tiny4412_resource)/sizeof(tiny4412_resource[0]), /*资源数量*/
	.resource=tiny4412_resource, /*资源结构体*/
	.dev=
	{
		.release=tiny4412_dev_release,
		.platform_data=&data,
	},
};

static int __init tiny4412_dev_dev_init(void) 
{
	/*1. 平台设备注册函数*/
	platform_device_register(&plat_dev);
	return 0;
}

static void __exit tiny4412_dev_dev_exit(void) 
{
	/*1. 平台设备注销函数*/
	platform_device_unregister(&plat_dev);
}

module_init(tiny4412_dev_dev_init);
module_exit(tiny4412_dev_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("tiny4412 wbyq");

平台驱动端代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/platform_device.h>

/*当设备端和驱动端名字匹配成功时调用*/
static int tiny4412_probe(struct platform_device *dev)
{
	printk("匹配的名称=%s\n",dev->name);
	printk("ID=%d\n",dev->id);
	printk("资源数量=%d\n",dev->num_resources);
	printk("寄存器起始地址=0x%X\n",dev->resource->start);
	printk("寄存器结束地址=0x%X\n",dev->resource->end);
	printk("私有数据=%d\n",*((int *)(dev->dev.platform_data)));

	/*编写驱动代码: 映射IO地址,注册杂项设备*/
	return 0;
}

/*资源卸载,设备端被卸载掉*/
static int tiny4412_remove(struct platform_device *dev)
{
	printk("资源卸载成功!\n");
	/*编写驱动代码: 取消映射IO地址,注销杂项设备*/
	return 0;
}

/*定义平台驱动端结构体*/
static struct platform_driver tiny4412_drv=
{
	.probe=tiny4412_probe,
	.remove=tiny4412_remove,
	.driver=
		{
			.name="tiny4412_platdev",
		},
};

static int __init tiny4412_drv_drv_init(void) 
{
	/*1. 平台驱动端注册*/
	platform_driver_register(&tiny4412_drv);
	return 0;
}

static void __exit tiny4412_drv_drv_exit(void) 
{
	/*2. 平台驱动端注销*/
	 platform_driver_unregister(&tiny4412_drv);
}

module_init(tiny4412_drv_drv_init);
module_exit(tiny4412_drv_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("tiny4412 wbyq");

任务2: IIC总线(IIC子系统

​ IIC总线特性:

1.​ 2条线 SDA数据线 ,SCL时钟线。

2.​ SDA数据线是双向。

3.​ 标准地址: 7位和10位。

4.​ IIC总线的信号: 起始信号、应答信号、非应答信号、停止信号、(读取一位数据、写一位数据)


 目标: 编写触摸屏驱动。



 去掉内核自带的驱动:

[root@wbyq linux-3.5]# make menuconfig

Device Drivers --->
Input device support --->

[*] Touchscreens --->

< > FocalTech ft5x0x TouchScreen driver 将*号去除掉。

重新编译内核,烧写内核。

烧写内核命令: [root@wbyq boot]# dd if=zImage of=/dev/sdb seek=1057


s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command,

u8 length, u8 *values)



触摸屏驱动代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/fcntl.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/timer.h>
#include <linux/miscdevice.h>
#include <linux/i2c.h>

static struct i2c_client *touch_client=NULL;

/*工作处理函数*/
static void tiny4412_work_func(struct work_struct *work)
{
	/*读取触摸屏的坐标值*/
	u8 buff[7];
	u32 x,y;
	i2c_smbus_read_i2c_block_data(touch_client,0,7,buff);/*读取第一个点*/
	x=(buff[3]&0xF)<<8|buff[4];
	y=(buff[5]&0xF)<<8|buff[6];
	
	printk("point=%d,x=%d,y=%d\n",buff[2]&0xF,x,y);
}

/*静态声明工作队列*/
static DECLARE_WORK(touch_wq,tiny4412_work_func);

/*触摸屏的中断服务函数*/
static irqreturn_t tiny4412_touch_handler(int irq, void *dev)
{
	schedule_work(&touch_wq);  /*将工作加入到一个工作队列里去*/
	return IRQ_HANDLED;
}

static int touch_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	u8 touch_id;
	printk("触摸屏驱动端匹配成功:0x%X\n",client->addr);
	touch_client=client;
	
	/*IIC子系统标准的读函数*/
	i2c_smbus_read_i2c_block_data(client,0xA3,1,&touch_id); /*读取厂家ID*/
	printk("厂家ID=%d\n",touch_id);

	/*注册中断*/
	request_irq(client->irq,tiny4412_touch_handler,IRQ_TYPE_EDGE_BOTH,client->name,NULL);
	return 0;
}

static int touch_remove(struct i2c_client *client)
{
	printk("触摸屏驱动端卸载成功!\n");

	/*释放中断号*/
	free_irq(client->irq,NULL);
	return 0;
}

static struct i2c_device_id touch_id[]=
{
	{"tiny4412_ft5x06",0},
	{}
};

static struct i2c_driver touch_driver=
{
	.probe=touch_probe,
	.remove=touch_remove,
	.driver=
		{
			.name="touch_drv",
		},
	.id_table=touch_id
};

static int __init tiny4412_touch_init(void) 
{
	/*1. 注册IIC子系统驱动端*/
	i2c_add_driver(&touch_driver);
	return 0;
}

static void __exit tiny4412_touch_exit(void) 
{
	/*2. 注销IIC子系统驱动端*/
	i2c_del_driver(&touch_driver);
}

module_init(tiny4412_touch_init);
module_exit(tiny4412_touch_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("tiny4412 wbyq");


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。