概述
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的实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复