Skip to content

[Only one cdev]Mpu6050 device - #29

Closed
sergiiromantsov wants to merge 29 commits into
Kernel-GL-HRK:Sergii.Romantsovfrom
sergiiromantsov:mpu6050_rsa
Closed

[Only one cdev]Mpu6050 device#29
sergiiromantsov wants to merge 29 commits into
Kernel-GL-HRK:Sergii.Romantsovfrom
sergiiromantsov:mpu6050_rsa

Conversation

@sergiiromantsov

Copy link
Copy Markdown

Improved mpu6050 implementation.
Added storage of data from mpu6050.
Added cdev to print data in one-line format.

sergiiromantsov and others added 29 commits October 22, 2017 21:52
Conflicts:
	lesson-04-memory-management/mm/xxx.c
This starts development of driver
for gyroscope & accelerometer mpu6050.
Some documentation for the device is attached.

Signed-off-by: Aleksandr Bulyshchenko <A.Bulyshchenko@globallogic.com>
Driver skeleton consist of two functions:
1. Module entry point (mpu6050_init)
   This function is called when driver is loaded.
   Should return 0 on success (driver will be loaded) or negative  error value
   on failure (driver will not be loaded).
2. Module exit point (mpu6050_exit)
   This function is called on driver removal. No return value.

Both functions should be exported using module_init and module_exit macroses.

Debug information is printed using printk() function and can be read using
dmesg program.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Device tree information contained in .dts and .dtsi files.
BBB-specific device are described in the am335x-bone-common.dtsi file.
It should be changed to include mpu6050 configuration.

So copy linux/arch/arm/boot/dts/am335x-bone-common.dtsi
from beagleboard/linux tag: 4.9.58-ti-r72.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Signed-off-by: Aleksandr Bulyshchenko <A.Bulyshchenko@globallogic.com>
Fix checkpatch errors in code of examples for lessons 2-4 (includding int80),
sysfs and procfs examples by Oleg Tsiliuric are left as is.

Signed-off-by: Aleksandr Bulyshchenko <A.Bulyshchenko@globallogic.com>
Mpu6050 is an i2c device and will be connected
to the i2c2 port on BBB.

So its descripton should be added to the i2c2 section
which is in am335x-bone-common.dtsi
and contains the following information (minimal) :

1. compatible = "gl,mpu6050";
   This is a driver match string, i2c driver should contain the same string
   in the id_table.

2. reg = <0x68>;
   Device i2c address. Includes r/w bit.

3. status = "okay";
   Not okay devices won't be loaded.

Also dtb make rule created to replace dtsi in tree and rebuild the dtb.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
I2C driver consist of:

1. probe and remove functions. Called on driver load and removal respectively.

2. i2c_device_id structure. Should contain strings exact equal to devive tree.
   MODULE_DEVICE_TABLE() macro is mandatory for match with dtb. Without it
   driver will not be probed.
   static const struct i2c_device_id mpu6050_idtable [] = {
       { "gl_mpu6050", 0 },
       { }
   };
   MODULE_DEVICE_TABLE(i2c, mpu6050_idtable);

3. i2c_driver structure itself.
   Important fields: probe, remove and id_table should point to items described
   above.
   static struct i2c_driver mpu6050_i2c_driver = {
       .driver = {
           .name = "gl_mpu6050",
       },

       .probe = mpu6050_probe ,
       .remove = mpu6050_remove,
       .id_table = mpu6050_idtable,
   };

I2C driver is created using i2c_add_driver(&mpu6050_i2c_driver) function.
It will return 0 on success and most likely is called from module_init().
Please note that without device tree match probe function will not be called,
but i2c_add_driver() will return OK. With device tree match, probe function
will be called right after i2c_add_driver().

I2C driver is removed with i2c_del_driver(&mpu6050_i2c_driver) function.
If driver was created, remove function will be called.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Most of i2c chips have a special read-only register with unique id.
So the easiest way to communicate with the device is to read that register.
It should be accessibe even during power off modes and so failing to read it
means no communication with the device. Reading non-expected value will indicate
wrong adress or data size used, or incorrect device connected (other revision).

Reading small amounts of data is easiest done using i2c_smbus_read_byte()
or similar functions. Why smbus? Because they are wrappers to i2c_transfer()
function and have internal device address as a parameter. This eliminates need
to fill i2c_transfer structure for each small read or write.
Using i2c_transfer() should be considered for large blocks of data and gives
a performance boost over i2c_smbus wrappers.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
This mpu6050 driver functionality consist of reading relevant values and
exporting them to the user space. Needed parameters are: accelerometer x,
y, z, gyroscope x, y, z and temperature (as an easiest check that device
is configured and operating properly).

First, the chip must be configured. This consist of programming all setup
registers with correct values. For example: clear power down, set prescalers,
configures fifos and so on.
Configuration is usually done in driver probe routine.

Second, reading values or performing needed actions can be done in a separate
theread inside driver, or in the workqueue. But this driver is supposed to
give values on demand so there is no need for that. All values are read at
once in a single function.

To export data to the user space was decided to use sysfs.
A class was created and 7 attributes for each parameter. Since all
parameters are read-only, all attributes have only show function and
their access rights are set to 0444.
So all _show() fuctions are almost the same: read all parameters first,
then return the needed one.

The summary how this driver works:
1. Create i2c device in module_init() and configure the chip from i2c_probe().
2. Create sysfs class and attributes for each parameter from module_init().
3. Read and return mpu6050 parameters in each sysfs_attribute_x_show().

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Conflicts:
	lesson-04-memory-management/mm/xxx.c
This starts development of driver
for gyroscope & accelerometer mpu6050.
Some documentation for the device is attached.

Signed-off-by: Aleksandr Bulyshchenko <A.Bulyshchenko@globallogic.com>
Driver skeleton consist of two functions:
1. Module entry point (mpu6050_init)
   This function is called when driver is loaded.
   Should return 0 on success (driver will be loaded) or negative  error value
   on failure (driver will not be loaded).
2. Module exit point (mpu6050_exit)
   This function is called on driver removal. No return value.

Both functions should be exported using module_init and module_exit macroses.

Debug information may be printed using printk() function and can be read using
dmesg program. But checkpatch.pl script treat printk(KERN_INFO as warnings
so pr_info() was used instead.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Device tree information contained in .dts and .dtsi files.
BBB-specific device are described in the am335x-bone-common.dtsi file.
It should be changed to include mpu6050 configuration.

So copy linux/arch/arm/boot/dts/am335x-bone-common.dtsi
from beagleboard/linux tag: 4.9.58-ti-r72.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Mpu6050 is an i2c device and will be connected
to the i2c2 port on BBB.

So its description should be added to the i2c2 section
which is in am335x-bone-common.dtsi
and contains the following information (minimal) :

1. compatible = "gl,mpu6050";
   This is a driver match string, i2c driver should contain the same string
   in the id_table.

2. reg = <0x68>;
   Device i2c address. Includes r/w bit.

3. status = "okay";
   Not okay devices won't be loaded.

Also dtb make rule created to replace dtsi in tree and rebuild the dtb.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
I2C driver consist of:

1. probe and remove functions. Called on driver load and removal respectively.

2. i2c_device_id structure. Should contain strings exact equal to devive tree.
   MODULE_DEVICE_TABLE() macro is mandatory for match with dtb. Without it
   driver will not be probed.
   static const struct i2c_device_id mpu6050_idtable [] = {
       { "mpu6050", 0 },
       { }
   };
   MODULE_DEVICE_TABLE(i2c, mpu6050_idtable);

3. i2c_driver structure itself.
   Important fields: probe, remove and id_table should point to items described
   above.
   static struct i2c_driver mpu6050_i2c_driver = {
       .driver = {
           .name = "gl_mpu6050",
       },

       .probe = mpu6050_probe ,
       .remove = mpu6050_remove,
       .id_table = mpu6050_idtable,
   };

I2C driver is created using i2c_add_driver(&mpu6050_i2c_driver) function.
It will return 0 on success and most likely is called from module_init().
Please note that without device tree match probe function will not be called,
but i2c_add_driver() will return OK. With device tree match, probe function
will be called right after i2c_add_driver().

I2C driver is removed with i2c_del_driver(&mpu6050_i2c_driver) function.
If driver was created, remove function will be called.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
Most of i2c chips have a special read-only register with unique id.
So the easiest way to communicate with the device is to read that register.
It should be accessibe even during power off modes and so failing to read it
means no communication with the device. Reading non-expected value will indicate
wrong adress or data size used, or incorrect device connected (other revision).

Reading small amounts of data is easiest done using i2c_smbus_read_byte()
or similar functions. Why smbus? Because they are wrappers to i2c_transfer()
function and have internal device address as a parameter. This eliminates need
to fill i2c_transfer structure for each small read or write.
Using i2c_transfer() should be considered for large blocks of data and gives
a performance boost over i2c_smbus wrappers.

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
This mpu6050 driver functionality consist of reading relevant values and
exporting them to the user space. Needed parameters are: accelerometer x,
y, z, gyroscope x, y, z and temperature (as an easiest check that device
is configured and operating properly).

First, the chip must be configured. This consist of programming all setup
registers with correct values. For example: clear power down, set prescalers,
configures fifos and so on.
Configuration is usually done in driver probe routine.

Second, reading values or performing needed actions can be done in a separate
theread inside driver, or in the workqueue. But this driver is supposed to
give values on demand so there is no need for that. All values are read at
once in a single function.

To export data to the user space was decided to use sysfs.
A class was created and 7 attributes for each parameter. Since all
parameters are read-only, all attributes have only show function and
their access rights are set to 0444.
So all _show() fuctions are almost the same: read all parameters first,
then return the needed one.

The summary how this driver works:
1. Create i2c device in module_init() and configure the chip from i2c_probe().
2. Create sysfs class and attributes for each parameter from module_init().
3. Read and return mpu6050 parameters in each sysfs_attribute_x_show().

Signed-off-by: Andriy.Khulap <andriy.khulap@globallogic.com>
… into mpu6050_rsa

Conflicts:
	mpu6050/mpu6050.c
 - Instead of sysfs class used sysfs kobject
 - Files-data created at once
 - Reading of data is done by one function
 - Controlled resources on initialization failure
Added functionality to hold 10 last reads of data from mpu6050 device.
Data from device mpu6050 will be read not often than 1 time per second.
Fixed missrint in storing timestamp: it was possibility to
store diff of timestams instead of real value.
Added charetcer-device that allows to read mpu6050-device data in
one-line format.
@sergiiromantsov sergiiromantsov changed the title [Only one cdev]Mpu6050 rsa [Only one cdev]Mpu6050 device Nov 15, 2017
Comment thread mpu6050/mpu6050_cdev.h
return &g_cdevs_holder;
}

static struct cdev_instance *get_cdev(dev_t dev_no)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing functions in header files is not recommended.
There are some exceptions like "wrappers" functions (e.g. i2c_smbus_read_word_swapped) but they should be declared as static inline.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in PR #33

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants