我是靠谱客的博主 土豪大船,最近开发中收集的这篇文章主要介绍g-sensor驱动在linux的实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

g-sensor 驱动

裸板:  i2c 控制器驱动
	  g-snesor 驱动程序
	  
linux:
		i2c 控制器驱动程序 在内核中已经写好了
		
1.总线
	i2c-core.c
	__init i2c_init(void)
		bus_register(&i2c_bus_type);
		struct bus_type i2c_bus_type = {
  			.name   = "i2c",
  			.match    = i2c_device_match,
  			.probe    = i2c_device_probe,
  			.remove   = i2c_device_remove,
  			.shutdown = i2c_device_shutdown,
		};
2.设备
	i2c_client
		struct i2c_client {
			//从设备地址
			unsigned short addr;    /* chip address - NOTE: 7bit  */
			char name[I2C_NAME_SIZE];//设备ID
			struct device dev; //基类
			//代表一个I2C控制器 表示i2c_client
			//代表的芯片挂载了哪个I2C控制器上
			struct i2c_adapter *adapter;
			......
		};
	i2c_new_device

3. 设备驱动
	i2c_driver
	struct i2c_driver {
		struct device_driver driver;
		int (*probe)(struct i2c_client *, const struct i2c_device_id *);
		int (*remove)(struct i2c_client *);
		//存储了该driver可以驱动的芯片的ID列表
		const struct i2c_device_id *id_table;
	};
	i2c_add_driver
	i2c_del_driver
	i2c_device_match(struct device *dev, struct device_driver *drv);

在这里插入图片描述

	注意: 先将内核中自带的g-sensor驱动裁剪掉
	make menuconfig
		Device Drivers--->
			<*> Hardware Monitoring support --->
				< > Freescale MMA865X 3-Axis Accelerometor
	make uImage
	1) 向I2c-core添加设备
		kernel/umentation/i2c/instantiating-devices
		How to instantiate I2C devices
		Method 1a: Declare the I2C devices by bus number
		Method 1b: Declare the I2C devices via devicetree
		Method 1c: Declare the I2C devices via ACPI
		Method 2: Instantiate the devices explicitly
		Method 3: Probe an I2C bus for certain devices
		
		vi arch/arm/plat-s5p6818/device.c
		+ #include <linux/i2c.h>
		+ /*准备创建I2C设备必备的信息*/
		+ static struct i2c_board_info  __initdata mma8653x = {
		+ 	.type = "mma8653", //设备ID
		+ 	.addr = 0x1D //从设备地址
		+ }
		void __init nxp_board_devs_register (void)
		{
			//2, 该芯片挂载了第二个I2C控制器上, 
			//&mma8653x,创建I2C设备时需要的ID和从设备地址
			//1, 第二个参数给定的地址中只有一个I2C设备信息
			+ i2c_register_board_info (2, &mma8653x, 1);
		}
	make uImage 
	将新内核烧录到开发板
	cp arch/arm/boot/uImage /tftpboot
	tftp 48000000 uImage
	mmc write 48000000 800 3000

  vi mma8653_dev.c
	#include <linux/module.h>
	#include <linux/init.h>
	#include <linux/i2c.h>
	MODULE_LICENSE("GPL");
	static const struct i2c_device_id mma8653x_tab[] = 
	{
	  {"mma8653", 0 },
	  { },
	};
	int mma865x_probe (struct i2c_client *client,
    	          const struct i2c_device_id *id)
	{
	  printk ("enter %sn",__func__);
	  return 0;
	}
	int mma8563x_remove (struct i2c_client *client)
	{
	  printk ("enter %sn",__func__);
	  return 0;
	}
	struct i2c_driver mma8653 = 
	{
	  .driver = 
	  {
    	.name = "mma865x",
	    .owner = THIS_MODULE;
	  },
	  .id_table = mma865x_tab,
	  .prob = mma865x_probe,
	  .remove = mma865x_remove,
	};
	int __init mma8653_drv_init (void)
	{
	  i2c_add_driver (&mma8653);
	  return 0;
	}
	void __exit mma8653_drv_exit (void)
	{
	  i2c_del_driver (&mma8653);
	}
	module_init(mma8653_drv_init);
	module_exit(mma8653_drv_exit);
  添加完设备信息之后,就可以增加prob的功能
  混杂设备, 将那些不容易分类的设备成为混杂设备
	struct miscdevice  {
	  //主设备号固定为xxx,决定次设备号
	  //如果minor = MISC_DYNAMIC_MINOR 代表由系统分配次设备号
	  int minor;
	  //设备文件的名称
	  const char *name;
	  //设备对应的操作函数集合
	  const struct file_operations *fops;
	};
	extern int misc_register(struct miscdevice *misc);
	extern void misc_deregister(struct miscdevice *misc);
	misc_register
	misc_deregister
	i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command);
		client,要读哪个寄存器
		command, g-sensor寄存器的地址
	i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8 value);
		client,要写哪个寄存器
		command, g-sensor寄存器的地址
		value,要写入的值
		
	i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command, u8 length, u8 *values);
		client,要写哪个寄存器
		command,要读取的起始寄存器地址
		length, 要读取的字节数
		value,存储地址
		
	
   vi test.c
   arm-cortex_a9-linux-gnueabi-gcc test.c -o test
   cp test ../rootfs
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#define GETXYZ_CMD 0x10001
struct acc_info
{
  short x;
  short y;
  short z;
}acc;
int main (void)
{
  int fd = open("/dev/mma865x", O_RDWR);
  if (fd < 0)
  {
    perror("open failed");
    return -1; 
  }
  while (1) 
  {
    ioctl (fd, GETXYZ_CMD, &acc);
    printf ("x = %hd y = %hd z = %hdn", acc.x, acc.y, acc.z);
    sleep(1);
  }
  close (fd);
}

   vi mma8653_drv.c
   insmod mma8653_drv.ko
   ./test
	#include <linux/miscdevice.h>
	#include <linux/module.h>
	#include <linux/init.h>
	#include <linux/i2c.h>
	#include <linux/uaccess.h>
	#include <linux/fs.h>
	MODULE_LICENSE("GPL");

	#define GET_XYZ   0x10001
	typedef struct acc
	{
	  short x;
	  short y;
	  short z;
	}acc_t;

	static const struct i2c_device_id mma8653x_tab[] = 
	{
	  {"mma8653", 0 },
	  { },
	};

	void enter_active (void)
	{
	  usigned char data = 0;
	  //读取0X2A寄存器的内容
	  //详细时序实现I2C控制器驱动程序中
	  data = i2c_smbus_read_byte_data (g_client, 0x2A);
	  data |= 1;
	  i2c_smbus_write_byte_data (g_client, 0x2A, data);
	}
	void read_acc (acc_t *data)
	{
	  unsigned char buf[6] = {0};
	  //轮询是否产生了加速度值
	  while (!(i2c_smbus_read_byte_data (g_client, 0x00) & (1<<3)));
	  i2c_smbus_read_i2c_block_data(g_client, 0x01, 6, buf);
	
	  data->x = buf[0] << 8 | buf[1];
	  data->x = data->x >> 6;
	  data->y = buf[2] << 8 | buf[3];
	  data->y = data->y >> 6;
	  data->z = buf[4] << 8 | buf[5];
	  data->z = data->z >> 6;
	}

	long mma8653_ioctl (struct file *filep, unsigned int cmd, unsigned long arg)
	{
	  acc_t acc_data = {0};
	  int ret = 0;

	  if (cmd == GET_XYZ)
	  {
    	//设置为active模式
	    enter_active ();
	    //读取加速度值
	    read_acc (&acc_data);
	    //加速值拷贝到用户空间
	    ret = copy_to_user ((void *)arg, &acc_data, sizeof(acc_t));
	  } else{
    	return -EINVAL;
	  }

	  return 0;
	}
	struct file_operations mma8653_fops = 
	{
	  .owner = THIS_MODULE;
	  .unlocked_ioctl = mma8653_ioctl;
	};

	struct miscdevice mma8653_misc = 
	{
	  .minor = MISC_DYNAMIC_MINOR,
	  .name = "mma8653x",
	  .fops = &mma8653_fops,
	};
	struct i2c_client *g_client = NULL;

	int mma865x_probe 
	(struct i2c_client *client, const struct i2c_device_id *id)
	{
	  //保存芯片对应数据结构地址 以备后续使用
	  g_client = client;
	  /*准备设备号 cdev 操作函数集合 自动创建设备文件*/
	  misc_register (&mma8653_misc);
	  return 0;
	}
	int mma8563x_remove (struct i2c_client *client)
	{
	  misc_deregister (&mma8653_misc);
	  return 0;
	}
	struct i2c_driver mma8653 = 
	{
	  .driver = 
	  {
    	.name = "mma865x",
	    .owner = THIS_MODULE;
	  },
	  .id_table = mma865x_tab,
	  .prob = mma865x_probe,
	  .remove = mma865x_remove,
	};
	int __init mma8653_drv_init (void)
	{
	  i2c_add_driver (&mma8653);
	  return 0;
	}
	void __exit mma8653_drv_exit (void)
	{
	  i2c_del_driver (&mma8653);
	}
	module_init(mma8653_drv_init);
	module_exit(mma8653_drv_exit);

最后

以上就是土豪大船为你收集整理的g-sensor驱动在linux的实现的全部内容,希望文章能够帮你解决g-sensor驱动在linux的实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部