I. Summary
Bma220 gravity sensor driver involves three files: bma220.c bma220.h bma220_driver.c. Bma220.c is an API that contains the bma220 driver. bma220.h contains the bma220 Register address, and bma220_driver.c is the I2C device driver of bma220. Here we will analyze and modify the bma220_driver.c.
Ii. bma220_driver.c modification records
--- Bma220_driver.c2012-06-14 19:56:50. 000000000 + 0800 + + bma220_driver_new.c2012-06-17 16:23:46. 850824401 + 0800-92,7 + 92,8 # include <Linux/jiffies. h> # include "bma220.h"-# include <Linux/earlysuspend. h> + # include "bma220.c" // This must be added. Otherwise, the function + // # include <Linux/earlysuspend in bma220.c cannot be found during compilation. h> // the kernel is first transplanted, so the earlysuspend code is commented out first, the same below. # Include <Linux/mutex. h> # define networks @-324,7 + 325,7 @ struct mutex; struct workqueue_struct * queue_struct; struct work_structwork;-struct worker; + // struct worker; int enabled; # ifdef yamaha_sensors struct input_dev * input; @-542,11 + 543,12 {bma220acc_t ACC; int ret;-If (bma220_client = NULL) + If (bma220_client = NULL) {// This bracket must be added. Otherwise When the bma220_debug debug switch is enabled, the READ function always returns "-1 "! # Ifdef bma220_debug printk (kern_info "I2C driver not install \ n"); # endif return-1; ++} bma220_read_accel_xyz (& ACC ); # ifdef bma220_debug-1936,7 + 1938,7 @@. foPs = & bma220_fops,};-static int bma220_detect (struct i2c_client * client, int kind, + static int bma220_detect (struct i2c_client * client, // differences between old and new kernels, the kind parameter struct i2c_board_info * info is missing from the detect function of the new kernel. {struct i2c_adapter * adapter = client-> adapter; @-2057,10 + 2059,10} init_work (& Data-> Work, bma220_do_polling);-data-> early_suspend.level = upper;-data-> early_suspend.suspend = upper; -Data-> early_suspend.resume = bma220_early_resume;-encrypt (& Data-> early_suspend); + // data-> early_suspend.level = average; + // data-> average = average; + // data-> early_suspend.resume = region; + // region (& Data-> early_suspend); i2c_set_clientdata (bma220_client, data); err = misc_register (& bma_device ); @-2120,7 + 2122,7 @ return 0;}-static unsigned short normal_i2c [] = {i2c_client_end}; + // static unsigned short normal_i2c [] = {i2c_client_end }; // not used. Comment out i2c_client_insmod_1 (bma220); static const struct i2c_device_id bma220_id [] ={@- %7,7 + %9,7 @@},. class = i2c_class_hwmon ,. id_table = bma220_id ,-. address_data = & addr_data, + //. address_data = & addr_data, // no definition is found, comment out. probe = bma220_probe ,. remove = bma220_remove ,. detect = require, @-2157,3 + 2159,6 @ module_init (bma220_init); module_exit (bma220_exit); ++ module_description ("I2C acceleration sensor driver"); // Add the GPL protocol, otherwise, an error + module_license ("GPL") is returned when the driver module is dynamically loaded ");
Iii. BSP
The following is an excerpt from the related section bma220 in BSP:
/***********************************************************//************************* BMA220 **************************//***********************************************************/#define BMA220_INT6static struct i2c_board_info __initdata mini_i2c2_boardinfo[] = {{I2C_BOARD_INFO("bma220", 0x0b),.irq = OMAP_GPIO_IRQ(BMA220_INT),},};static int __init omap3_mini_i2c_init(void){omap_register_i2c_bus(1, 2600, mini_i2c1_boardinfo,ARRAY_SIZE(mini_i2c1_boardinfo));omap_register_i2c_bus(2, 100, mini_i2c2_boardinfo,ARRAY_SIZE(mini_i2c2_boardinfo));/* Bus 3 is attached to the DVI port where devices like the pico DLP * projector don't work reliably with 400kHz */omap_register_i2c_bus(3, 100, mini_i2c3_boardinfo,ARRAY_SIZE(mini_i2c3_boardinfo));return 0;}static void __init omap3_mini_init(void){omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);omap3_mini_i2c_init();platform_add_devices(omap3_mini_devices,ARRAY_SIZE(omap3_mini_devices));omap_serial_init();usb_musb_init();usb_ehci_init(&ehci_pdata);omap3mini_flash_init();/* Ensure SDRC pins are mux'd for self-refresh */omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);mini_display_init();}
4. Add the driver to the kernel
1. First create the sensors directory under the driver/MISC/directory
2. Add a line at the end of/driver/MISC/kconfig:
source "drivers/misc/sensors/Kconfig"
3. Add a line at the end of/driver/MISC/makefile:
obj-y+= sensors/
4. Add five files in the/driver/MISC/sensors/directory:
Bma220.c bma220.h bma220_driver.c kconfig makefile
Bma220_driver.c is the modified above, and bma220.c bma220.h is the original code.
The kconfig and makefile contents in the/driver/MISC/sensors/directory are as follows. The first item in kconfig is used to configure the bma220 device driver, the second item is used to configure the relative position of the chip on the front of the product.
## Sensor strange devices#menuconfig SENSORS_DEVICESbool "Sensors devices"default y---help--- Say Y here to get to see options for device drivers from various different categories. This option alone does not add any kernel code. If you say N, all options in this submenu will be skipped and disabled.if SENSORS_DEVICESconfig INPUT_BMA220 tristate "Bosch Sensortec BMA220 G-Sensor" depends on I2Cconfig INPUT_BMA220_POSITION int "BMA220 Mounting Position on Board" depends on INPUT_BMA220 default "0" help Chip mounting position (pin 1). 0: top, upper-left 1: top, upper-right 2: top, lower-right 3: top, lower-left 4: bottom, upper-left 5: bottom, upper-right 6: bottom, lower-right 7: bottom, lower-leftendif # SENSOR_DEVICES
obj-$(CONFIG_INPUT_BMA220)+= bma220_driver.o
This configuration is used in bma220_driver.c, as follows:
/* * Transformation matrix for chip mounting position */static const int bma220_position_map[][3][3] = {{{0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, /* top/upper-left */ /* 7627 */{{1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, /* top/upper-right */ /* 7625 */{{0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, /* top/lower-right */{{-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, /* top/lower-left */{{0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, /* bottom/upper-right */{{-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, /* bottom/upper-left */{{0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, /* bottom/lower-left */{{1, 0, 0} , {0, -1, 0} , {0, 0, -1} }, /* bottom/lower-right */};static int accel_xyz_transformation(int index, bma220acc_t acc){int data = 0;data += acc.x * bma220_position_map[CONFIG_INPUT_BMA220_POSITION][index][0];data += acc.y * bma220_position_map[CONFIG_INPUT_BMA220_POSITION][index][1];data += acc.z * bma220_position_map[CONFIG_INPUT_BMA220_POSITION][index][2];return data;}
The configuration page is as follows:
Finally, the configuration contained in the generated. config is as follows. The value of the third item is used in the above function compilation.
CONFIG_SENSORS_DEVICES=yCONFIG_INPUT_BMA220=mCONFIG_INPUT_BMA220_POSITION=0
5. testing applications
The application mainly configures bma220_set_suspend to 1 (the default value is 0, and the data read remains unchanged ). The Board is facing up on the back of the shell, so the test result is that the Board is facing up, the Z axis value reaches the negative minimum, and the Z axis value toward the back is the positive maximum value. The upper part of the board is horizontal, and the X-axis integer is the maximum value. Vertical, Y-axis integer maximum. Test results show that the driver is normal.
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include "bma220_cmd.h"int main(int argc, char *argv[]){int fd;int ret;unsigned int cmd;unsigned long arg;signed char data[3];printf("--------------------------------------------------------------\n");printf("--- This is the begining of the test program of my driver! ---\n");printf("--------------------------------------------------------------\n");sleep(1);/* 1. open the device driver */printf("\n1. open device driver:\n");fd = open("/dev/bma220", O_RDWR);if (fd < 0) {printf("Device open error!\n");exit(1);}usleep(500000);/* 2. set event/calibration/mode/range */cmd = BMA220_SOFT_RESET; ret = ioctl(fd, cmd);if(ret < 0)printf("ERR: BMA220_SOFT_RESET, ret = %d\n", ret);usleep(100000);/*cmd = BMA220_IOCTL_EVENT_CTRL; arg = 4;ret = ioctl(fd, cmd, &arg);if(ret < 0)printf("ERR: BMA220_IOCTL_EVENT_CTRL, ret = %d\n", ret);usleep(100000);*//*cmd = BMA220_IOCTL_CALIBRATION; ret = ioctl(fd, cmd);if(ret < 0)printf("ERR: BMA220_IOCTL_CALIBRATION, ret = %d\n", ret);usleep(100000);*/cmd = BMA220_SET_MODE; arg = 0;//Set mode: normal moderet = ioctl(fd, cmd, &arg);if(ret < 0)printf("ERR: BMA220_SET_MODE, ret = %d\n", ret);usleep(100000);cmd = BMA220_GET_MODE; ret = ioctl(fd, cmd, &arg);if(ret < 0)printf("ERR: BMA220_GET_MODE, ret = %d\n", ret);printf("Mode: %ld\n", arg);usleep(100000);cmd = BMA220_SET_RANGE; arg = 0;//Set range: param range 0=2g, 1=4g, 2=8g, 3=16gret = ioctl(fd, cmd, &arg);if(ret < 0)printf("ERR: BMA220_SET_MODE, ret = %d\n", ret);usleep(100000);cmd = BMA220_GET_RANGE; ret = ioctl(fd, cmd, &arg);if(ret < 0)printf("ERR: BMA220_GET_MODE, ret = %d\n", ret);printf("Range: %ld\n", arg);usleep(100000);cmd = BMA220_SET_SUSPEND; arg = 1; //Must be 1, otherwise the third step will be to read the same dataret = ioctl(fd, cmd, &arg);if(ret < 0)printf("ERR: BMA220_SET_SUSPEND, ret = %d\n", ret);printf("Suspend: %ld\n", arg);usleep(100000);/* 3. read x, y, z by read function*/while (1) {ret = read(fd, data, 3);if(ret < 0)printf("ERR: read x/y/z, ret = %d\n", ret);printf("x = %d, y = %d, z = %d.\n", data[0], data[1], data[2]);usleep(500000);}/* 4. close device driver */close(fd);printf("---------------------------------------------------------\n");printf("--- This is the end of the test program of my driver! ---\n");printf("---------------------------------------------------------\n");return 0;}