Reprinted, please indicate the source and author of the article!
Source: http://blog.csdn.net/xl19862005
By xandy)
Hardware Platform: Ti dm37xx
SENSOR: lsm330dlc (ACC + gyr)
1. Place the lsm330dlc driver code in the drivers/input/MISC directory, and add the following fields to the kconfig and makefile files in the directory:
Kconfig
Config sensors_lsm330dlc
Tristate "ST's family of MEMS sensor modules of lsm330dlc"
Depends on I2C & input & mach_zt6810
Select input_polldev
Default y
Help
This driver provides support for the lsm330dlc gyroscope and accelerator connected via I2C.
Makefile
OBJ-$ (config_sensors_lsm330dlc) + = lsm330dlc_acc.o lsm330dlc_gyr.o
2. Modify the interrupt Io and data enable IO in lsm330dlc. h according to the hardware schematic, for example:
/* Xandy modify the accelerator and gyro interrupt pins @ 2012/9/12 */
# Define int1_gpio_acc 178
# Define int2_gpio_acc 179
# Define int1_gpio_gyr 181
# Define int2_gpio_gyr 180
/* Xandy Add Sensors enable pin */
# Define sensor_en_gpio 38
3. Modify the BSP file (corresponding to the board-xx.c file), The lsm330dlc driver registration (I2C bus), such:
# Ifdef config_sensors_lsm330dlc
Static struct i2c_board_info _ initdata zt6810_i2c_lsm330dlc [] = {
{
I2c_board_info ("lsm330dlc_acc", 0x19 ),
},
{
I2c_board_info ("lsm330dlc_gyr", 0x6b ),
},
};
# Endif
Static int _ init zt6810_i2c_init (void)
{
Omap_register_i2c_bus (1, 2600, zt6810_i2c_boardinfo,
Array_size (zt6810_i2c_boardinfo ));
/* Bus 2 is used for battery ckeck (bq27410 )*/
# Ifdef config_battery_max17049
Omap_register_i2c_bus (2,100, zt6810_i2c_max17049, array_size (zt6810_i2c_max17049 ));
# Else
Omap_register_i2c_bus (2,100, null, 0 );
# Endif
/* Projector don't work reliably with 400 kHz */
# Ifdef config_sensors_lsm330dlc
Omap_register_i2c_bus (3,200, zt6810_i2c_lsm330dlc, array_size (zt6810_i2c_lsm330dlc ));
# Endif
Return 0;
}
After the kernel is compiled, the uimage will be burned to the prototype. If there is no accident, go to the corresponding directory on the serial port terminal and LS will see the following content:
The ACC is successfully registered on the I2C bus. The corresponding I2C bus number and address are 3-0019, while gyr is 3-006b.
4. Enter the following command in the serial port:
# Cat/proc/bus/input/devices
The following information is displayed:
# Cat/proc/bus/input/devices
I: Bus = 0019 vendor = 0001 Product = 0001 version = 0100
N: Name = "gpio-keys"
P: phys = gpio-keys/input0
S: sysfs =/devices/platform/gpio-keys/input/input0
U: uniq =
H: handlers = KBD event0
B: EV = 3
B: Key = 4 0 0 0 100000 0 0 0
I: Bus = 0019 vendor = 0001 Product = 0001 version = 0003
N: Name = "twl4030 keypad"
P: phys = twl4030_keypad/input0
S: sysfs =/devices/platform/OMAP/omap_i2c.1/i2c-1/1-004a/twl4030_keypad/input/input1
U: uniq =
H: handlers = KBD event1
B: EV = 100013
B: Key = 800 c1680 0 2000000 100000aa
B: MSC = 10
I: Bus = 0000 vendor = 0000 Product = 0000 version = 0000
N: Name = "ads7846 touchscreen"
P: phys = spi1.0/input0
S: sysfs =/devices/platform/omap2_mcspi.1/spi1.0/input/input2
U: uniq =
H: handlers = mouse0 event2
B: EV = B
B: Keys = 400 0 0 0 0 0 0 0 0 0 0
B: ABS = 1, 1000003
I: Bus = 0000 vendor = 0000 Product = 0000 version = 0000
N: Name = "twl4030_pwrbutton"
P: phys = twl4030_pwrbutton/input0
S: sysfs =/devices/platform/OMAP/omap_i2c.1/i2c-1/1-0049/twl4030_pwrbutton/input/input3
U: uniq =
H: handlers = KBD event3
B: EV = 3
B: Key = 100000 0 0 0
I: Bus = 0018 vendor = 0000 Product = 0000 version = 0000
N: Name = "lsm330dlc_acc"
P: phys =
S: sysfs =/devices/platform/OMAP/omap_i2c.3/i2c-3/3-0019/input/input4
U: uniq =
H: handlers = js0 event4
B: EV = 9
B: ABS = 100 107
I: Bus = 0018 vendor = 0000 Product = 0000 version = 0000
N: Name = "lsm330dlc_gyr"
P: phys =
S: sysfs =/devices/platform/OMAP/omap_i2c.3/i2c-3/3-006b/input/input5
U: uniq =
H: handlers = JS1 event5
B: EV = 9
B: ABS = 7
Some information about the input devices already registered by the system is listed here. The last two items are the corresponding input devices registered by the previously added sensor (ACC + gyr ).
Why is the sensor registered as an input device? See the following content in the driver source code:
Static int lsm330dlc_acc_input_init (struct lsm330dlc_acc_data * ACC)
{
Int err;
Init_delayed_work (& acc-> input_work, lsm330dlc_acc_input_work_func );
ACC-> input_dev = input_allocate_device ();
If (! ACC-> input_dev ){
Err =-enomem;
Dev_err (& acc-> client-> Dev, "input device allocation failed \ n ");
Goto err0;
}
ACC-> input_dev-> open = lsm330dlc_acc_input_open;
ACC-> input_dev-> close = lsm330dlc_acc_input_close;
ACC-> input_dev-> name = lsm330dlc_acc_dev_name;
// Acc-> input_dev-> name = "accelerometer ";
ACC-> input_dev-> ID. bustype = bus_i2c;
ACC-> input_dev-> Dev. Parent = & acc-> client-> dev;
Input_set_drvdata (acc-> input_dev, ACC );
Set_bit (ev_abs, ACC-> input_dev-> evbit );
/* Next is used for interrupta sources data if the case */
Set_bit (abs_misc, ACC-> input_dev-> absbit );
/* Next is used for interruptb sources data if the case */
Set_bit (abs_wheel, ACC-> input_dev-> absbit );
Input_set_abs_params (acc-> input_dev, abs_x,-g_max, g_max, fuzz, flat );
Input_set_abs_params (acc-> input_dev, abs_y,-g_max, g_max, fuzz, flat );
Input_set_abs_params (acc-> input_dev, abs_z,-g_max, g_max, fuzz, flat );
/* Next is used for interrupta sources data if the case */
Input_set_abs_params (acc-> input_dev, abs_misc, int_min, int_max, 0, 0 );
/* Next is used for interruptb sources data if the case */
Input_set_abs_params (acc-> input_dev, abs_wheel, int_min, int_max, 0, 0 );
Err = input_register_device (acc-> input_dev );
If (ERR ){
Dev_err (& acc-> client-> Dev,
"Unable to register input device % s \ n ",
ACC-> input_dev-> name );
Goto err1;
}
Return 0;
Err1:
Input_free_device (acc-> input_dev );
Err0:
Return err;
}
Enter the following command in the terminal:
# Getevent
The following information is displayed:
# Getevent
Cocould not get driver version for/dev/input/mice, not a typewriter
Add device 1:/dev/input/event2
Name: "ads7846 touchscreen"
Cocould not get driver version for/dev/input/mouse0, not a typewriter
Add device 2:/dev/input/event0
Name: "gpio-keys"
Add device 3:/dev/input/event5
Name: "lsm330dlc_gyr"
Cocould not get driver version for/dev/input/JS1, invalid argument
Add Device 4:/dev/input/event4
Name: "lsm330dlc_acc"
Cocould not get driver version for/dev/input/js0, invalid argument
Add Device 5:/dev/input/event1
Name: "twl4030 keypad"
Add device 6:/dev/input/event3
Name: "twl4030_pwrbutton"
/Dev/input/event4: 0003 0000 00000001
/Dev/input/event4: 0003 0001 ffffff5f
/Dev/input/event4: 0003 0002 000003df
/Dev/input/event4: 0000 0000 00000000
/Dev/input/event4: 0003 0000 fffffffe
/Dev/input/event4: 0003 0001 ffffff5e
/Dev/input/event4: 0003 0002 000003e2
/Dev/input/event4: 0000 0000 00000000
/Dev/input/event4: 0003 0000 00000002
/Dev/input/event4: 0003 0001 ffffff5d
/Dev/input/event4: 0003 0002 000003e5
/Dev/input/event4: 0000 0000 00000000
/Dev/input/event4: 0003 0000 00000001
/Dev/input/event4: 0003 0001 ffffff5f
/Dev/input/event4: 0003 0002 000003df
/Dev/input/event4: 0000 0000 00000000
/Dev/input/event4: 0003 0000 fffffffe
/Dev/input/event4: 0003 0001 ffffff66
/Dev/input/event4: 0003 0002 000003e4
......
The getevent command is used to obtain system input events. It is easy to see that event4 events have always occurred in the current system:
Add Device 4:/dev/input/event4
Name: "lsm330dlc_acc"
It can be seen that the added sensor (ACC) has started to work and continuously reports the current acceleration event to the system!
If the sensor driver is properly configured and compiled, but the information cannot be obtained, you need to check whether your hardware is normal, such as: whether the chip is consistent; whether there is virtual soldering, find an oscilloscope and check if the I2C waveform is abnormal!
5. After completing the above work, it does not mean that you have completed all the work. Now, although the sensor has started to work, when you enter the gravity sensing interface, such as system settings.
I found that the UI does not rotate at present, or that the next sensor test tool is the same.
This is because there is no channel for reporting the sensor event in Hal. Let's take a look at how to modify the code in Hal.
The sensor Hal Layer Code is in
Hardware/Ti/omap3/libsensors
Directory.
Let's take a look at the sensors. cpp file. The sensor is encapsulated in the Hal layer.
Struct sensors_module_t hal_module_info_sym = {
Common :{
Tag: hardware_module_tag,
Version_major: 1,
Version_minor: 0,
ID: sensors_hardware_module_id,
Name: "sensor module ",
Author: "Texas Instruments Inc .",
Methods: & sensors_module_methods,
},
Get_sensors_list: sensors _ get_sensors_list,
};
This is a standard structure encapsulated by the Hal layer. Let's take a look at the following code:
Sensors_poll_context_t: sensors_poll_context_t ()
{
Msensors [accel] = new accelsensor ();
Mpollfds [accel]. FD = msensors [accel]-> getfd ();
Mpollfds [accel]. Events = Pollin;
Mpollfds [accel]. revents = 0;
Msensors [gyro] = new gyrosensor ();
Mpollfds [gyro]. FD = msensors [gyro]-> getfd ();
Mpollfds [gyro]. Events = Pollin;
Mpollfds [gyro]. revents = 0;
Int wakefds [2];
Int result = pipe (wakefds );
Loge_if (result <0, "error creating wake pipe (% s)", strerror (errno ));
Fcntl (wakefds [0], f_setfl, o_nonblock );
Fcntl (wakefds [1], f_setfl, o_nonblock );
Mwritepipefd = wakefds [1];
Mpollfds [Wake]. FD = wakefds [0];
Mpollfds [Wake]. Events = Pollin;
Mpollfds [Wake]. revents = 0;
}
We can see that there are two new sensor devices, one is ACC, and the other is gyr! Enter accelsensor. cpp in the following constructor:
Accelsensor: accelsensor ()
: Sensorbase (null, "lsm330dlc_acc "),
Menabled (0 ),
Minputreader (4 ),
Mhaspendingevent (false)
{
Memset (& mpendingevent, 0, sizeof (mpendingevent ));
Mpendingevent. Version = sizeof (sensors_event_t );
Mpendingevent. Sensor = id_a;
Mpendingevent. type = sensor_type_accelerometer;
Mpendingevent. Acceleration. Status = sensor_status_accuracy_high;
If (data_fd)
{
Strcpy (input_sysfs_path,
Accel_sensor_name );
Input_sysfs_path_len = strlen (input_sysfs_path );
Enable (0, 1 );
}
}
The yellow background annotation needs to be modified. The macro definition of accel_sensor_name is as follows:
/* Xandy add accelsensor name and gyrosensor name macro definition */
# Ifdef config_sensor_lsm330dlc
# Define accel_sensor_name "/sys/bus/I2C/Drivers/lsm330dlc_acc/3-0019 /"
# Define gyro_sensor_name "/sys/bus/I2C/Drivers/lsm330dlc_gyr/3-006b /"
# Else
# Define accel_sensor_name "/sys/bus/I2C/Drivers/lis331dlh/1-0018 /"
# Define gyro_sensor_name "/sys/bus/I2C/Drivers/lda-4200dh_i2c/1-0068 /"
# Endif
The macro switch config_sensor_lsm330dlc is defined as follows in the corresponding Android. mk:
# Xandy add macro define for accel and gyro sensors
Ifeq ($ (sensor_lsm330dlc), true)
Local_cflags + =-dconfig_sensor_lsm330dlc
Endif
Sensor_lsm330dlc is defined as follows in boardconfig. mk of the corresponding project (under the Device directory, corresponding to your vendor at this time:
# Xandy add accel and gyro sensors
Board_has_sensor: = true
Sensor_lsm330dlc: = true
These are actually macro definitions and compilation switch settings. This is designed to facilitate switching between different projects (vendor) and add new device support.
The modification of gyr Hal is the same as that of ACC. I will not mention it here!
After these modifications, use mm to compile the corresponding lib and push the lib to the directory of the prototype file system through ADB. If everything works properly after the system is restarted, now you can enter the UI rotation interface, and it will take effect,
However, the rotation direction is quite different from the running direction at this time, so you have to modify the following macro in sensors. h In sensor HAL:
# Ifdef config_sensor_lsm330dlc
# Define event_type_accel_x rel_x
# Define event_type_accel_y rel_y
# Define event_type_accel_z rel_z
# Else
# Error you must define accel X Y Z
# Endif
# Ifdef config_sensor_lsm330dlc
# Define event_type_gyro_x rel_x // rel_rx
# Define event_type_gyro_y rel_y // rel_ry
# Define event_type_gyro_z rel_z // rel_rz
# Else
# Error you must define gyro X Y Z
# Endif
Modify the definitions of X, Y, and Z as follows:
# Ifdef config_sensor_lsm330dlc
# Define event_type_gyro_x rel_z
# Define event_type_gyro_y rel_x
# Define event_type_gyro_z rel_y
# Else
# Error you must define gyro X Y Z
# Endif
Depends on the location of your hardware.
Now the sensor debugging has basically been completed. If there is anything to modify, it will be fine-tuned, such as sensitivity.