linux Gsensor驱动(bma250为…
来源:互联网 发布:java常见错误 编辑:程序博客网 时间:2024/05/22 01:38
1 Gsensor驱动概述
图中包含三个部分:hardware,driver, input:
n
n
n
实际使用时,驱动按照一定的时间间隔,通过数据总线,获取gsensor hardware采集到的数据,并按照操作系统的要求,将这些信息通过input core上报给操作系统。
2Gsensor驱动设计要求
由gsensor驱动在系统中的层次,上有Input core,下有I2C,驱动需要通过I2C采集信息,并准确及时的上报数据至input core。驱动上报的数据,是被input core管理并被上层使用的,应符合input core和上层应用框架的要求;
2.1符合Input输入子系统的设计规范
n
n
n
2.2I2c总线的配置
要使用i2c总线进行数据传输,需注册i2c driver,创建i2c-client,以便使用i2c-adapter进行数据传输;
要成功注册i2cdriver有两种方式:
n
n
需要说明的是,此两种方式可共存,目前2.6就是这样的;在共存时,以i2c_register_board_info信息为更高优先级,在i2c_register_board_info已经占用设备的前提下,内核发现设备被占用,不会执行detect,因而不会有冲突。
3gsensor模块硬件说明
n
n
n
3.1gsensor硬件连接
Gsensor在硬件上,只有i2c连接,这些连接信息,需要事先告知驱动,从而从指定的设备上读取数据;这些连接信息,通过sysconfig1描述,在驱动中使用;
4 驱动设计
4.1 支持模组列表
在A1x平台上支持Gsensor列表如下:
支持的
模组
Chip ID
寄存器
Chip ID值
I2C地址
I2C设备注册
名称
unuse_name
bma250
0x00
3
0x18
bma250
bma250
bma222
0x00
3
0x08
bma250
bma222
bma150
0x00
2
0x38
bma250
bma150
kxtik-1004
0x0f
0x05
0x0f
kxtik
kxtik
kxtj9-1005
0x0f
0x08
0x0f
kxtik
kxtik
dmard06
0x0f
0x06
0x1c
dmard06
dmard06
mma7660
无
无
0x4c
mma7660
mma7660
mma8452
0x0d
0x2a
SA0 = 0: 0x1c
mma8452
mma8452c
SA0 = 1: 0x1d
Mma8452d
afa750
0x37
0x3d or 0x3c
0x3d
afa750
afa750
mxc6225
无
无
0x15
mxc622x
mxc622x
4.2Gsensor配置
在A1x的方案中,Gsensor的配置在sys_config1.fex文件中:
gsensor_used
gsensor_name
gsensor_twi_id
gsensor_twi_addr
4.3 关键数据结构
4.3.1 i2c_driver
static struct i2c_driverbma250_driver = {
};
在驱动程序中,静态初始化i2c_driver结构体给bma250_driver变量,该变量完成gsensor驱动的主要工作,匹配设备名,设备的侦测等,文件操作结构体如上所示。
4.3.2 bma250_data
struct bma250_data{
#ifdefCONFIG_HAS_EARLYSUSPEND
#endif
};
代表了gsensor驱动所需要的信息的集合,用于帮助实现对采样信息的处理。
4.3.3 delayed_work
struct delayed_work{
};
Delayed_work一般用来触发定时的操作,在定时时间到后,完成指定操作,通过不断的触发定时操作,实现按照一定频率的执行指定操作;
4.3.4 bma250acc
struct bma250acc{
} ;
用于记录采样时获得的信息。
5 驱动流程解析
5.1模块加载
static struct i2c_driverbma250_driver = {
};
static int __initBMA250_init(void)
{
}
static void __exitBMA250_exit(void)
{
}
module_init(BMA250_init);
module_exit(BMA250_exit);
n
n
n
5.2bma250初始化工作-probe
static intbma250_probe(struct i2c_client *client,
{
}
在bma250_probe函数中,主要完成了以下几件事:
n
n
n
n
n
n
下面对以上这些工作做详细解释,分配数据内存空间就不讲了
5.2.1 读取IICchip id
在4.1的列表中,我们可以看到bma250的chip ID寄存器为0x00,chip ID的值为3。而上面代码有两个宏的定义:
#defineBMA250_CHIP_ID_REG
#defineBMA250_CHIP_ID
调用IIC接口i2c_smbus_read_word_data()读取IIC上bma250的chip id,返回的值tempvalue=3的时候,说明是正确的!
5.2.2 初始化工作队列
先提一个问题,为什么要创建工作队列?在前面的介绍中我们知道,sensor传感器获取数据后,将数据传给controller的寄存器中,供主控去查询读取数据。所以这里创建的工作队列,就是在一个工作者线程,通过IIC不断的去查询读取controller上的数据。
工作队列的作用就是把工作推后,交由一个内核线程去执行,更直接的说就是如果写了一个函数,而现在不想马上执行它,想在将来某个时刻去执行它,那用工作队列准没错.大概会想到中断也是这样,提供一个中断服务函数,在发生中断的时候去执行,没错,和中断相比,工作队列最大的好处就是可以调度可以睡眠,灵活性更好。
上面代码中我们看到INIT_DELAYED_WORK(&data->work,bma250_work_func),其实是一个宏的定义,在include/linux/workqueue.h中。bma250_work_func()就是我们定义的功能函数,用于查询读取Sensor数据的,并上报Input子系统,代码如下:
static voidbma250_work_func(struct work_struct *work)
{
}
我们调用INIT_DELAYED_WORK()宏初始化了工作队列之后,那么什么时候将执行我们定义的功能函数bma250_work_func()呢?那么只需要调用schedule_delayed_work()即可在delay时间后执行功能函数。
在驱动设计中,我们在Sensor使能函数中调用schedule_delayed_work()开始启动工作队列,调用cancel_delayed_work_sync()停止工作队列。而我们在上面的功能函数bma250_work_func()中也调用了schedule_delayed_work(),这样功能函数将被重复调用,也就可以按照一个设定的频率查询读取Sensor数据了。然后通过input系统提供的接口函数input_report_abs(),向input系统报告新的数据。
5.2.3向input系统注册
Gsensor作为一个输入设备,按照linux设计标准,需要将Gsensor驱动注册到Input子系统中,注册代码如下:
static intbma250_input_init(struct bma250_data *bma250)
{
}
就是由上面的代码,完成了Gsensor驱动向Input子系统注册,又三个步骤:
n
n
n
5.2.4 创建sysfs接口
为什么要创建sysfs接口?在驱动层创建了sysfs接口,HAL层通过这些sysfs接口,对Sensor进行操作,如使能、设置delay等。
5.2.4.1 sysfs接口函数的建立DEVICE_ATTR
说道sysfs接口,就不得不提到函数宏
#define DEVICE_ATTR(_name,_mode, _show, _store) \
struct device_attributedev_attr_##_name = __ATTR(_name, _mode, _show, _store)
函数宏DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法:
n
n
当然_ATTR不是独生子女,他还有一系列的姊妹__ATTR_RO宏只有读方法,__ATTR_NULL等等:
n
n
n
n
对于DEVICE_ATTR(_name,_mode, _show, _store)的四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。
如果你完成了DEVICE_ATTR函数宏的填充,下面就需要创建接口了。例如如下:
1)
2)
3)
5.2.4.2 bma250驱动sysfs接口建立
Bma250驱动sysfs接口建立,按照5.2.4.1上面介绍的三个步骤来实现。
n
static DEVICE_ATTR(delay,S_IRUGO|S_IWUSR|S_IWGRP,
static DEVICE_ATTR(enable,S_IRUGO|S_IWUSR|S_IWGRP,
static struct attribute*bma250_attributes[] = {
};
n
static structattribute_group bma250_attribute_group = {
};
n
在bma250的初始化函数probe中——bma250_probe(),调用:
errsysfs_create_group(&data->input->dev.kobj,&bma250_attribute_group);
到此,完成了sysfs接口的创建,我们可以在根文件系统中看到/sys/class/input/input3/目录,在该目录下我们可以看到多个节点,其中就包含了enable和delay。我们以enable为例子,可以有两种方法完成对Gsensor的使能工作:
1)
$cd/sys/class/input/input3
$echo 1 >enable
将1写到enable节点,那么将“1”作为参数调用到驱动的bma250_enable_store()方法,完成对Gsensor的使能工作。
2)
char buffer[20];
int len = sprintf(buffer,"%d\n", 1);
fd =open(“/sys/class/input/input3/enable”, O_RDWR);
write(fd, value,len)
5.3 读取并上报数据
在Android的HAL层,通过对/sys/class/input/input3/enable节点的写操作,使能Gsensor。调用到的方法是bma250_enable_store():
static ssize_tbma250_enable_store(struct device *dev,
{
}
static voidbma250_set_enable(struct device *dev, int enable)
{
}
我们看到了,在使能函数中,调用了schedule_delayed_work()开始工作队列,于是调用了功能函数bma250_work_func()
static voidbma250_work_func(struct work_struct *work)
{
}
在上面代码中,调用bma250_read_accel_xyz()方法读取Gsensor的三个数据,然后调用Input系统的接口函数input_report_abs()进行数据的上报。可以看到,当读取一次数据后,继续调用schedule_delayed_work()开始下一个工作队列,由此,功能函数bma250_work_func()将会按照一个的频率被执行。
那么对于HAL层,将通过/dev/input/event3设备节点读取到Gsensor数据。到此,Gsensor驱动的工作流程完毕。应该很好理解吧!
6 驱动调试
1)确保硬件各个管脚的连接顺序正确;
2)上电,测试各个管脚信号的电压正常,只有在保证硬件正常的情况下,进行软件驱动调试,方可保证驱动能够正常工作(该处最容易被很多软件开发人员忽视,务必注意,方可节省大部分时间)
3)将串口打印信息打开,串口打印信息设置:在打包工具中的crane-win-v2\wboot\bootfs\linux目录下的params和paramsr两个文件中的语句的最后加入loglevel=9即可。gsensor驱动中所有的打印信息打开,查看驱动程序的配置信息读取状态以及I2C的初始化状态。
4)查看probe是否成功,如probe不成功,根据打印信息定位驱动的运行情况,是因为什么原因导致失败。
5)当probe成功之后,gsensor没反应,查看打印信息,是否enable,确保enable。
6)查看i2c通信状态,当串口打印信息显示i2C通信失败时,主要有以下两个原因,一是硬件上的,各个信号线接触不良,所以出现通信失败时,检查各引脚接触情况和电压情况。二是因为I2C的地址不正确导致,因为i2C地址为7位地址,所以可能是因为在配置的时候没有移位或者是主控IC有多个I2C地址,导致地址不匹配。在已知i2C地址的情况下,可以通过尝试的方法,进行I2C地址的匹配;在不知道I2C地址的情况下,可以通过扫描的方法查看在哪一个地址时,有应答,即可知道I2C通信地址,在将正确的地址填写sysconfig配置文件中即扫描i2c地址的示例代码如下所示:
static int goodix_iic_test(struct i2c_client *client)
{
}
若以上两种方法都不能正确进行i2c传输,则打开i2c传输打印,查看传输打印状态,在编译服务器上,目录为workspace\exdroid\lichee\linux-2.6.36上,输入命令:
make ARCH=arm menuconfig,选择Device Drivers->I2Csupport->I2C Hardware Bussupport->SUN4I_IIC_PRINT_TRANSFER_INFO,输入Y进入bus num id(accepatableinput:0,1,2)(new),输入数值,,若希望打印信息,数值对应相应的IIC号,gsensorIC用的是第二组,因此选择数值为2,若不希望打印信息,输入N退出保存即可。进行修改后,需要重新编译打包之后才能生效。
7)可使用adb工具查看驱动是否加载以及gsensor是否有反应,adb工具需要安装设备对应的驱动。使用adb shell工具查看驱动是否存在于机器中以及驱动是否已经加载,以及gsensor之后是否有反应。同时可以作为简单的调试工具,修改好的驱动PUSH到机器中,重启系统之后即可运行新的驱动,不用重新打包(配置文件内容除外)。使用到的命令如下所示:
adbshell
adb push xx.ko/drv
cd
ls
lsmod
rmmod
insmod
getevent
参考:
工作队列:http://blog.csdn.net/zchill/article/details/7076561
SYsfs接口:http://blog.csdn.net/manshq163com/article/details/7848714
- linux Gsensor驱动(bma250为…
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- linux Gsensor驱动(bma250为例子)
- bma250驱动
- BMA250传感器驱动
- Gsensor:BMA250E驱动实现
- Gsensor驱动概述
- 从Tiny4412--mma7660 gsensor驱动探索Linux内核I2C总线驱动框架
- linux gsensor demo
- gsensor
- gsensor
- Shiro 权限框架使用总结
- Android Input Framework(三)---InputReader&InputDispatcher
- Launcher定制
- JNI demo 手把手教例子
- linux学习文档--有时间看看
- linux Gsensor驱动(bma250为…
- 《Android技术内幕:系统卷》
- 深入理解android:卷1
- 《疯狂Android讲义》
- Android wallpape service
- NFC framework introduce(一)
- NFC framework introduce(二)
- NFC bcm2079x驱动学习
- Android一键锁屏开发全过程…