-
Notifications
You must be signed in to change notification settings - Fork 22
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 mpu6050 #146
Open
daaaanil81
wants to merge
11
commits into
Kernel-GL-HRK:Daniil.Petrov
Choose a base branch
from
daaaanil81:lessonMpu6050
base: Daniil.Petrov
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
Lesson mpu6050 #146
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
48e16c5
Lesson 5: Add simple module
daaaanil81 95d7bd7
Lesson 5: Add header for modules
daaaanil81 71d0b36
Lesson 5: Add functions for new i2c device
daaaanil81 c17a7d7
Lesson 5: Create classes for sysfs
daaaanil81 ed28cfc
Lesson 5: Realize function for temperature
daaaanil81 028ef25
Lesson 5: Modify function for temperature
daaaanil81 96ed8aa
Lesson 5: Correct error in function for temperature
daaaanil81 c358e03
Lesson 5: Realize functions for accelograph
daaaanil81 8ce4f0d
Lesson 5: Realize functions for gyroscope
daaaanil81 5787d4b
Lesson 5: Add Makefile for compiletion
daaaanil81 1ac7a2d
Lesson 5: Add README file
daaaanil81 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
obj-m := mpu6050.o | ||
KERNELDIR=/home/danilpetrov/Kernel | ||
export ARCH = arm | ||
export CROSS_COMPILE ?= arm-linux-gnueabihf- | ||
|
||
|
||
.PHONY: all clean | ||
|
||
all: | ||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules | ||
|
||
clean: | ||
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,11 @@ | ||
# MPU6050 Practice. Kernel object module development | ||
|
||
## Homework | ||
|
||
1. Create simplest driver (kernel object module) using compiled kernel (by Armbian or without it) | ||
and cross-compiler. | ||
2. Fix errors in driver mpu6050 from repository. | ||
3. Сompile it using cross-compiler. | ||
4. Deploy and run it. Check output using dmesg. | ||
5. Check modified DTS. | ||
6. Check driver’s output by reading value from sysfs |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,276 @@ | ||
#include <linux/module.h> | ||
#include "mpu6050_reg.h" | ||
#include <linux/version.h> | ||
#include <linux/proc_fs.h> | ||
#include <linux/sched.h> | ||
#include <linux/kernel.h> | ||
#include <linux/types.h> | ||
#include <linux/kdev_t.h> | ||
#include <linux/fs.h> | ||
#include <linux/device.h> | ||
#include <linux/cdev.h> | ||
#include <linux/uaccess.h> | ||
#include <linux/slab.h> | ||
#include <linux/sysfs.h> | ||
#include <linux/err.h> | ||
#include <linux/i2c.h> | ||
#include <linux/i2c-dev.h> | ||
#define DISCHARGE 1000 | ||
#define SIXTEEN 65536 | ||
|
||
|
||
struct mpu6050_data { | ||
struct i2c_client *drv_client; | ||
int accel_values[3]; | ||
int gyro_values[3]; | ||
int temperatureC[2]; | ||
int temperatureF[2]; | ||
}; | ||
|
||
static struct mpu6050_data gl_mpu6050_data; | ||
static struct class *class_device; | ||
|
||
static ssize_t accel_x_show(struct class *class, struct class_attribute *attr, char *buf); | ||
static ssize_t accel_y_show(struct class *class, struct class_attribute *attr, char *buf); | ||
static ssize_t accel_z_show(struct class *class, struct class_attribute *attr, char *buf); | ||
static ssize_t gyro_x_show(struct class *class, struct class_attribute *attr, char *buf); | ||
static ssize_t gyro_y_show(struct class *class, struct class_attribute *attr, char *buf); | ||
static ssize_t gyro_z_show(struct class *class, struct class_attribute *attr, char *buf); | ||
static ssize_t temperature_show(struct class *class, struct class_attribute *attr, char *buf); | ||
|
||
struct class_attribute accel_x_attr = __ATTR(ACCEL_X, 0444, &accel_x_show, NULL); | ||
struct class_attribute accel_y_attr = __ATTR(ACCEL_Y, 0444, &accel_y_show, NULL); | ||
struct class_attribute accel_z_attr = __ATTR(ACCEL_Z, 0444, &accel_z_show, NULL); | ||
|
||
struct class_attribute gyro_x_attr = __ATTR(GYRO_X, 0444, &gyro_x_show, NULL); | ||
struct class_attribute gyro_y_attr = __ATTR(GYRO_Y, 0444, &gyro_y_show, NULL); | ||
struct class_attribute gyro_z_attr = __ATTR(GYRO_Z, 0444, &gyro_z_show, NULL); | ||
|
||
struct class_attribute temperature_attr = __ATTR(TEMP, 0444, &temperature_show, NULL); | ||
|
||
static ssize_t accel_x_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_ACCEL_XOUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_ACCEL_XOUT_L); | ||
t = (h << 8 | l); | ||
gl_mpu6050_data.accel_values[0] = (t & 0x7fff) - (t & 0x8000); | ||
printk(KERN_INFO "Accel_X: [%d]\n", gl_mpu6050_data.accel_values[0]); | ||
sprintf(buf, "Accel_X: [%d]\n", gl_mpu6050_data.accel_values[0]); | ||
return strlen(buf); | ||
} | ||
static ssize_t accel_y_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_ACCEL_YOUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_ACCEL_YOUT_L); | ||
t = (h << 8 | l); | ||
gl_mpu6050_data.accel_values[1] = (t & 0x7fff) - (t & 0x8000); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the reason for this conversation? Variable t is already 16 bit long. |
||
printk(KERN_INFO "Accel_Y: [%d]\n", gl_mpu6050_data.accel_values[1]); | ||
sprintf(buf, "Accel_Y: [%d]\n", gl_mpu6050_data.accel_values[1]); | ||
return strlen(buf); | ||
} | ||
static ssize_t accel_z_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_ACCEL_ZOUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_ACCEL_ZOUT_L); | ||
t = (h << 8 | l); | ||
gl_mpu6050_data.accel_values[2] = (t & 0x7fff) - (t & 0x8000); | ||
printk(KERN_INFO "Accel_Z: [%d]\n", gl_mpu6050_data.accel_values[2]); | ||
sprintf(buf, "Accel_Z: [%d]\n", gl_mpu6050_data.accel_values[2]); | ||
return strlen(buf); | ||
|
||
} | ||
static ssize_t gyro_x_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_GYRO_XOUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_GYRO_XOUT_L); | ||
t = (h << 8 | l); | ||
gl_mpu6050_data.gyro_values[0] = (t & 0x7fff) - (t & 0x8000); | ||
printk(KERN_INFO "Gyro_X: [%d]\n", gl_mpu6050_data.gyro_values[0]); | ||
sprintf(buf, "Gyro_X: [%d]\n", gl_mpu6050_data.gyro_values[0]); | ||
return strlen(buf); | ||
} | ||
static ssize_t gyro_y_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_GYRO_YOUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_GYRO_YOUT_L); | ||
t = (h << 8 | l); | ||
gl_mpu6050_data.gyro_values[1] = (t & 0x7fff) - (t & 0x8000); | ||
printk(KERN_INFO "Gyro_Y: [%d]\n", gl_mpu6050_data.gyro_values[1]); | ||
sprintf(buf, "Gyro_Y: [%d]\n", gl_mpu6050_data.gyro_values[1]); | ||
return strlen(buf); | ||
} | ||
static ssize_t gyro_z_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_GYRO_ZOUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_GYRO_ZOUT_L); | ||
t = (h << 8 | l); | ||
gl_mpu6050_data.gyro_values[2] = (t & 0x7fff) - (t & 0x8000); | ||
printk(KERN_INFO "Gyro_Z: [%d]\n", gl_mpu6050_data.gyro_values[2]); | ||
sprintf(buf, "Gyro_Z: [%d]\n", gl_mpu6050_data.gyro_values[2]); | ||
return strlen(buf); | ||
} | ||
static ssize_t temperature_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
uint8_t h; | ||
uint8_t l; | ||
uint16_t t; | ||
int result; | ||
printk(KERN_INFO "Show_Temperature\n"); | ||
h = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_TEMP_OUT_H); | ||
l = i2c_smbus_read_byte_data(gl_mpu6050_data.drv_client, REG_TEMP_OUT_L); | ||
t = (h << 8 | l); | ||
result = ((t & 0x7fff) - (t & 0x8000)); | ||
result = result*DISCHARGE/340 + 12420*DISCHARGE/340; | ||
gl_mpu6050_data.temperatureC[0] = result / DISCHARGE; | ||
gl_mpu6050_data.temperatureC[1] = result % DISCHARGE; | ||
gl_mpu6050_data.temperatureF[0] = ((result*9/5)+32*DISCHARGE)/DISCHARGE; | ||
gl_mpu6050_data.temperatureF[1] = ((result*9/5)+32*DISCHARGE) % DISCHARGE; | ||
printk(KERN_INFO "Temperature: %d.%03d C\n", gl_mpu6050_data.temperatureC[0], gl_mpu6050_data.temperatureC[1]); | ||
printk(KERN_INFO "Temperature: %d.%03d F\n", gl_mpu6050_data.temperatureF[0], gl_mpu6050_data.temperatureF[1]); | ||
sprintf(buf,"Temperature: %d.%03d C\nTemperature: %d.%03d F\n", gl_mpu6050_data.temperatureC[0], gl_mpu6050_data.temperatureC[1], gl_mpu6050_data.temperatureF[0], gl_mpu6050_data.temperatureF[1]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How mane symbols in this string? Please check your code with checkpatch.pl |
||
return strlen(buf); | ||
} | ||
|
||
static int mpu6050_probe(struct i2c_client *drv_client, const struct i2c_device_id *id) | ||
{ | ||
int ret; | ||
dev_info(&drv_client->dev, "i2c driver probed\n"); | ||
dev_info(&drv_client->dev, "i2c client address is 0x%X\n", drv_client->addr); | ||
|
||
ret = i2c_smbus_read_byte_data(drv_client, REG_WHO_AM_I); | ||
if (IS_ERR_VALUE(ret)) { | ||
dev_err(&drv_client->dev, "i2c_smbus_read_byte_data() failed with error: %d\n", ret); | ||
return ret; | ||
} | ||
if (ret != MPU6050_WHO_AM_I) { | ||
dev_err(&drv_client->dev, "wrong i2c device found: expected 0x%X, found 0x%X\n", MPU6050_WHO_AM_I, ret); | ||
return -1; | ||
} | ||
dev_info(&drv_client->dev, "i2c mpu6050 device found, WHO_AM_I register value = 0x%X\n", ret); | ||
|
||
i2c_smbus_write_byte_data(drv_client, REG_CONFIG, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_GYRO_CONFIG, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_ACCEL_CONFIG, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_FIFO_EN, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_INT_PIN_CFG, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_INT_ENABLE, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_USER_CTRL, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_PWR_MGMT_1, 0); | ||
i2c_smbus_write_byte_data(drv_client, REG_PWR_MGMT_2, 0); | ||
|
||
gl_mpu6050_data.drv_client = drv_client; | ||
return 0; | ||
} | ||
|
||
static int mpu6050_remove(struct i2c_client *drv_client) | ||
{ | ||
dev_info(&drv_client->dev, "i2c driver remove\n"); | ||
gl_mpu6050_data.drv_client = 0; | ||
return 0; | ||
} | ||
|
||
static const struct i2c_device_id mpu6050_id[] = { | ||
{ "mpu6050", 0 }, | ||
{ } | ||
}; | ||
|
||
MODULE_DEVICE_TABLE(i2c, mpu6050_id); | ||
|
||
static struct i2c_driver mpu6050_i2c_driver = { | ||
.driver = { | ||
.name = "gl_mpu6050", | ||
}, | ||
.probe = mpu6050_probe, | ||
.remove = mpu6050_remove, | ||
.id_table = mpu6050_id, | ||
}; | ||
static int mpu6050_init(void) | ||
{ | ||
int ret; | ||
ret = i2c_add_driver(&mpu6050_i2c_driver); | ||
printk(KERN_INFO "mpu6050: module add\n"); | ||
|
||
if ((class_device = class_create(THIS_MODULE, NAME_SYSCLASS)) < 0) { | ||
printk(KERN_ERR "Mpu6050: Error with create class_create.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &accel_x_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file accel_x_attr.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &accel_y_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file accel_y_attr.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &accel_z_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file accel_z_attr.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &gyro_x_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file gyro_x_attr.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &gyro_y_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file gyro_y_attr.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &gyro_z_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file gyro_z_attr.\n"); | ||
return -ENOMEM; | ||
} | ||
ret = class_create_file(class_device, &temperature_attr); | ||
if (ret < 0) { | ||
printk(KERN_ERR "Mpu6050: Error wih create file temperature_attrs.\n"); | ||
return -ENOMEM; | ||
} | ||
return 0; | ||
} | ||
|
||
static void mpu6050_exit(void) | ||
{ | ||
|
||
i2c_del_driver(&mpu6050_i2c_driver); | ||
printk(KERN_INFO "mpu6050: module del\n"); | ||
class_remove_file(class_device, &accel_x_attr); | ||
class_remove_file(class_device, &accel_y_attr); | ||
class_remove_file(class_device, &accel_z_attr); | ||
class_remove_file(class_device, &gyro_x_attr); | ||
class_remove_file(class_device, &gyro_y_attr); | ||
class_remove_file(class_device, &gyro_z_attr); | ||
class_remove_file(class_device, &temperature_attr); | ||
class_destroy(class_device); | ||
} | ||
|
||
module_init(mpu6050_init); | ||
module_exit(mpu6050_exit); | ||
|
||
MODULE_LICENSE("GPL"); | ||
MODULE_AUTHOR("Danil Petrov <[email protected]>"); | ||
MODULE_DESCRIPTION("My module for mpu6050 on GY-521"); | ||
MODULE_VERSION("0.1"); | ||
|
||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef _MPU6050_REG_H | ||
#define _MPU6050_REG_H | ||
|
||
#define REG_CONFIG 0x1A | ||
#define REG_GYRO_CONFIG 0x1B | ||
#define REG_ACCEL_CONFIG 0x1C | ||
#define REG_FIFO_EN 0x23 | ||
#define REG_INT_PIN_CFG 0x37 | ||
#define REG_INT_ENABLE 0x38 | ||
#define REG_ACCEL_XOUT_H 0x3B | ||
#define REG_ACCEL_XOUT_L 0x3C | ||
#define REG_ACCEL_YOUT_H 0x3D | ||
#define REG_ACCEL_YOUT_L 0x3E | ||
#define REG_ACCEL_ZOUT_H 0x3F | ||
#define REG_ACCEL_ZOUT_L 0x40 | ||
#define REG_TEMP_OUT_H 0x41 | ||
#define REG_TEMP_OUT_L 0x42 | ||
#define REG_GYRO_XOUT_H 0x43 | ||
#define REG_GYRO_XOUT_L 0x44 | ||
#define REG_GYRO_YOUT_H 0x45 | ||
#define REG_GYRO_YOUT_L 0x46 | ||
#define REG_GYRO_ZOUT_H 0x47 | ||
#define REG_GYRO_ZOUT_L 0x48 | ||
#define REG_USER_CTRL 0x6A | ||
#define REG_PWR_MGMT_1 0x6B | ||
#define REG_PWR_MGMT_2 0x6C | ||
#define REG_WHO_AM_I 0x75 | ||
|
||
#define MPU6050_WHO_AM_I 0x68 | ||
#define ACCEL_X accel_x | ||
#define ACCEL_Y accel_y | ||
#define ACCEL_Z accel_z | ||
|
||
#define GYRO_X gyro_x | ||
#define GYRO_Y gyro_y | ||
#define GYRO_Z gyro_z | ||
|
||
#define TEMP Temperature | ||
|
||
#define NAME_SYSCLASS "Mpu6050" | ||
#endif | ||
|
||
|
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible to read complete work using i2c_smbus_read_word_swapped()