以下是mpu6050简单的驱动实现,mpu6050是I2C接口的6轴传感器,可以作为字符设备注册到内核,本代码运行环境是3.4.2内核,4.3.2版本的编译链,12.04版本的Ubuntu,硬件环境是jz2440开发板;

按照之前分析的I2C驱动框架,mpu6050驱动主要是实现外设端的驱动,主要是注册外设到I2C总线,而外设端注册到I2C总线包括device及driver两个部分注册到I2C总线,采用分离的设计思想,详情见代码:

device注册到I2C总线:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>static const unsigned short addr_list[] = { 0x50,0x68, I2C_CLIENT_END };
static struct i2c_board_info mpu6050_info = {.type = "mpu6050",
};
static struct i2c_client *mpu6050_client;static int mpu6050dev_init ( void )
{struct i2c_adapter *i2c_adap;i2c_adap = i2c_get_adapter ( 0 );mpu6050_client = i2c_new_probed_device ( i2c_adap, &mpu6050_info, addr_list, NULL );i2c_put_adapter ( i2c_adap );if ( mpu6050_client )return 0;elsereturn -ENODEV;
}
static void mpu6050dev_exit ( void )
{i2c_unregister_device ( mpu6050_client );}module_init ( mpu6050dev_init );
module_exit ( mpu6050dev_exit );
MODULE_LICENSE ( "GPL" );

注:为实现动态加载驱动模块,使用了 i2c_new_probed_device  函数,该函数的关键作用是在把设备注册到总线之前,会判断该设备的地址是否真实有效,或者也可以说是该设备是否真实存在;另外也可以使用i2c_new_device函数来加载一个设备到总线,但是该函数类似I2C总线总force属性,会强制认为加载的设备地址真实有效,或者是强制认为当前的设备真实存在,  另外在把mpu6050关联到I2C适配器上时,调用了 i2c_get_adapter ( 0 ) 函数,由于S3C2440只有一个I2C适配器,所以该函数的参数直接写0,即第一个适配器;

接下来是设备驱动加载到I2C总线:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>static ssize_t mpu6050_write ( struct file *file, const char __user *buf, size_t, loff_t *offset );
static ssize_t mpu6050_read ( struct file *file, char __user *buf, size_t size, loff_t *offset );
static int mpu6050drv_probe ( struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id );
static int mpu6050drv_remove ( struct i2c_client *i2c_client );static struct i2c_device_id mpu6050drv_id =
{.name = "mpu6050",.driver_data = 0x68,};static struct i2c_driver mpu6050drv =
{.driver    = {.name    = "mympu6050",.owner    = THIS_MODULE,},.probe = mpu6050drv_probe,.remove = mpu6050drv_remove,.id_table = &mpu6050drv_id,};/* 字符设备相关 */
int major = 0;
static struct cdev mpu6050_cdev;
static struct file_operations mpu6050ops =
{.owner = THIS_MODULE,.read = mpu6050_read,.write = mpu6050_write,
};static struct class *cls;
static ssize_t mpu6050_read ( struct file *file, char __user *buf, size_t size, loff_t *offset )
{return 0;
}static ssize_t mpu6050_write ( struct file *file, const char __user *buf, size_t size, loff_t *offset )
{return 0;
}
static int mpu6050drv_probe ( struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id )
{dev_t dev = 0;printk ( "mpu6050drv_probe\r\n" );
#if 0/* 把mpu6050当做字符设备注册到内核 */major = register_chrdev ( 0, "mpu6050", &mpu6050ops );
#elsealloc_chrdev_region ( &dev, 0, 2, "mpu6050_region" );        // 占用2个次设备号cdev_init ( &mpu6050_cdev, &mpu6050ops );mpu6050_cdev.owner = THIS_MODULE;cdev_add ( &mpu6050_cdev, dev, 2 );                            // 占用2个次设备号#endifcls = class_create ( THIS_MODULE, "mpu6050cls" );major = MAJOR ( dev );device_create ( cls, NULL, MKDEV ( major, 0 ), NULL, "mpu6050" );
//    device_create ( cls, NULL, MKDEV ( major, 1 ), NULL, "mpu6050_2" );return 0;
}
static int mpu6050drv_remove ( struct i2c_client *i2c_client )
{printk ( "mpu6050drv_remove\r\n" );unregister_chrdev_region ( 0, 1 );cdev_del ( &mpu6050_cdev );device_destroy ( cls, MKDEV ( major, 0 ) );
//    device_destroy ( cls, MKDEV ( major, 1 ) );
    class_destroy ( cls );return 0;
}
static int mpu6050_init ( void )
{i2c_add_driver ( &mpu6050drv );return 0;
}static void mpu6050_exit ( void )
{i2c_del_driver ( &mpu6050drv );}module_init ( mpu6050_init );
module_exit ( mpu6050_exit );
MODULE_LICENSE ( "GPL" );

当设备加载到I2C总线,外设驱动也加载到总线后,I2Ccore会调用match函数,匹配 mpu6050drv 结构体总 id_table  成员里的name是否和加载的外设名一致,如果一致就会进行绑定,然后调用外设驱动的probe函数,这样I2C驱动就基本上完成了,接下来就是根据外设的具体情况去处理了,比如如果外设是mpu6050、则当做字符设备注册到内核,然后编写读写函数,这些就已经不是I2C驱动框架之内的工作了,而是字符设备驱动的范畴了;

本驱动没有具体去实现mpu6050的读写过程,具体的代码完全可以借用裸机版的代码,本实例仅供I2C驱动框架参考。

转载于:https://www.cnblogs.com/weishengzhong/p/7468397.html

linux驱动之i2c子系统mpu6050设备驱动相关推荐

  1. 【Linux驱动】I2C子系统与触摸屏驱动

    由于学习触摸屏驱动涉及到中断以及I2C相关的知识,因此先介绍一下I2C的驱动框架. 触摸屏与I2C总线的关系 关于I2C的基础概念和原理参考我的这篇博客:[裸机]嵌入式相关问题汇总(二.I2C通信概念 ...

  2. linux驱动之I2C子系统

    目录 一.I2C基本原理 二.linux内核的I2C子系统详解 1.linux内核的I2C驱动框架总览 2.I2C子系统的4个关键结构体(kernel/include/linux/i2c.h) 3.关 ...

  3. Linux驱动分析——I2C子系统

    stm32mp157  盘古开发板  Linux内核版本4.19 目录 1.朱有鹏老师视频笔记 2.I2C子系统的4个关键结构体 3.关键文件 4.i2c-core.c初步分析 ​4.1.smbus代 ...

  4. linux 块设备驱动 (三)块设备驱动开发

    linux 块设备驱动 (三)块设备驱动开发 一: 块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数是 register_blkdev(),其原型为: int ...

  5. 嵌入式Linux驱动笔记(五)------学习platform设备驱动

    你好!这里是风筝的博客, 欢迎和我一起交流. 设备是设备,驱动是驱动. 如果把两个糅合写一起,当设备发生变化时,势必要改写整个文件,这是非常愚蠢的做法.如果把他们分开来,当设备发生变化时,只要改写设备 ...

  6. linux 设备驱动(一)——字符设备驱动

    linux 设备驱动(一)--字符设备驱动 一.概述 1.1 设备驱动介绍 1.2. 设备结构 1.2.1 设备号 1.2.2 驱动层次 1.3 设备驱动对外接口 1.4 设备驱动特点 二.字符设备驱 ...

  7. i2c子系统-----mpu6050

    1. I2C驱动开发: I2C从设备驱动开发 硬件芯片:从设备 cmos camera ts :电容触摸屏 gsenor: 重力传感器 eeprom: 存储设备 HDMI:高清输出接口 2. i2c子 ...

  8. linux i2c子系统看不懂啊,Linux 下的I2C子系统

    Linux 下的I2C子系统 2013.7.16 本文分为两部分,一.设备模型 二.平台相关 . ================================================ 第一 ...

  9. 设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动

    以下内容转载于微信公众号:嵌入式企鹅圈.如有侵权,请告知删除. 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sysfs等相关概念和技术. 对于初学者来说会非常 ...

最新文章

  1. 别再打字聊bug了,GitHub支持“视频留言”!手机也可以的那种
  2. linux收缩java位置,找到linux中当前java的安装位置
  3. A6.2021年全国数学建模竞赛C题分析-生产企业原材料的订购与运输
  4. Carlosfu技术系列文章总目录
  5. 分布式 开源_3个开源分布式跟踪工具
  6. eureka上的微服务不能通过服务名调用_掌门教育微服务体系 Solar | 阿里巴巴 Nacos 企业级落地上篇...
  7. androidstudio 日历视图怎么显示农历_ipad自带的日历程序
  8. python小软件实例教程_【趣味案例】用Python做一个时光回忆录小软件,女朋友当场流泪说非我不嫁!...
  9. GCC的gcc和g++区别,本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已
  10. 评侯捷的《深入浅出MFC》和李久进的《MFC深入浅出》
  11. Excel修改默认分页符(仅仅在特定行后可插入分页符)
  12. 自学网站大全(值得收藏)
  13. jeecgBoot 的JSelectDepart 部门选择组件使用
  14. activity串行多实例会签
  15. 有翅膀的java游戏_翅膀只是为了拉风?在这几款游戏中,带上翅膀真的能飞
  16. 2017-2018-1 20155228 《信息安全系统设计基础》第三周学习总结
  17. 人人商城报错:服务器暂时无法处理您的请求,请稍后再试,解决方案
  18. 详解GloVe词向量模型
  19. 美团 键盘大小写转换 最小敲击次数
  20. LC39 Combination Sum

热门文章

  1. pythonurllib标准_Python标准库urllib2的一些使用细节总结
  2. python数据分析第七章实训3_《利用python进行数据分析》读书笔记--第七章 数据规整化:清理、转换、合并、重塑(二)...
  3. android 不重新加载,android – 返回Activity而不重新创建(不调用onCreate())
  4. linux怎么创建用户教程,在Linux中如何手动创建一个用户
  5. (一)神经网络训练不起来怎么办:局部最小值(local minia)与鞍点(saddle point)
  6. 和12岁小同志搞创客开发:手撕代码,做一款人体感应灯
  7. 读后感与机翻《从视频中推断力量和学习人类效用》
  8. Linux那些事儿之我是Sysfs(5)举例二sculld
  9. 机器学习(2)特征提取1 -- 字典特征提取
  10. 【Pandas库】(1) Series的创建方法