Linux驱动开发_平台设备总线、IIC总线、编写触摸屏驱动
【摘要】 介绍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 ---> [*] 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)