-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lesson 5, imu driver and chdevs #20
Open
srybalko
wants to merge
49
commits into
Kernel-GL-HRK:Serhii.Rybalko
Choose a base branch
from
srybalko:Serhii.Rybalko
base: Serhii.Rybalko
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This starts development of driver for gyroscope & accelerometer mpu6050. Some documentation for the device is attached. Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
…he second is for reading buffered imu data from last 10 second. Multiple file opening doesn't handled
- Add .gitignore file for C language - Update README.md Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
- hello - HelloWorld Linux module; - dependencies - Linux modules dependencies. Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
- int80 - syscalls implementation examples by Oleg Tsiliuric; - procfs_rw - procfs example; - sys - sysfs examples by Oleg Tsiliuric. Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
Update declaration to use CLASS_ATTR_RW macro. Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
- examples.245.proc - procfs examples by Oleg Tsiliuric Task: porte to your kernel version (v4.13). Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
- mm - skeleton to the driver, based on module xxx from sysfs example. Task: Add dynamic memory allocation to ”xxx” driver from sysfs example using kmalloc and kmem_cache API. Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
This starts development of driver for gyroscope & accelerometer mpu6050. Some documentation for the device is attached. Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
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 <[email protected]>
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 <[email protected]>
Signed-off-by: Aleksandr Bulyshchenko <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
…he second is for reading buffered imu data from last 10 second. Multiple file opening doesn't handled
@srybalko,
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(old (for 11/08/17)) Refactoring of lesson 5 code. There aren't any changes in previous lessons, they will be added later.
(new (for 11/15/17)) MPU6050 module create two chdevs for reading imu data stream in realtime and buffered imu data for last 10 secs. Data bufferization use a simple ring buffer, data reading is in kthread. IMU data has timestamps. Multiple chdev file access isn't handled. Coding standarts: any errors, a lot of warnings.
@AleksandrBulyshchenko, that pull request was changed