I2C裝置驅動移植之重力感應器BMA220

來源:互聯網
上載者:User

 一、綜述

BMA220重力感應器的驅動一共涉及三個檔案:bma220.c bma220.h bma220_driver.c。bma220.c是包含BMA220驅動涉及到的API,bma220.h包含BMA220寄存器地址等,bma220_driver.c是BMA220的I2C裝置驅動。我們這裡分析和修改,主要就是針對這個bma220_driver.c。


二、bma220_driver.c修改記錄

--- 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"//這個必須添加,否則編譯時間找不到使用到的bma220.c中的函數+//#include<linux/earlysuspend.h>//先是在linux核心下做移植,故先注釋掉earlysuspend相關代碼,下同。 #include <linux/mutex.h>  #define BMA220_MAJOR101@@ -324,7 +325,7 @@ struct mutex mutex; struct workqueue_struct*queue_struct; struct work_structwork;-struct early_suspend early_suspend;+//struct early_suspend early_suspend; 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) {//這個括弧必須加,否則在BMA220_DEBUG調試開關開啟時,read函數始終返回“-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,//新舊核心的差異,較新核心的detect函數少了kind參數   struct i2c_board_info *info) { struct i2c_adapter *adapter = client->adapter;@@ -2057,10 +2059,10 @@ }  INIT_WORK(&data->work, bma220_do_polling);-data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;-data->early_suspend.suspend = bma220_early_suspend;-data->early_suspend.resume = bma220_early_resume;-register_early_suspend(&data->early_suspend);+//data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;+//data->early_suspend.suspend = bma220_early_suspend;+//data->early_suspend.resume = bma220_early_resume;+//register_early_suspend(&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};//未用到,注釋掉 I2C_CLIENT_INSMOD_1(bma220);  static const struct i2c_device_id bma220_id[] = {@@ -2137,7 +2139,7 @@ }, .class= I2C_CLASS_HWMON, .id_table= bma220_id,-.address_data= &addr_data,+//.address_data= &addr_data,//未找到定義處,注釋掉 .probe= bma220_probe, .remove= bma220_remove, .detect= bma220_detect,@@ -2157,3 +2159,6 @@  module_init(BMA220_init); module_exit(BMA220_exit);++MODULE_DESCRIPTION("I2C Acceleration Sensor Driver");//添加GPL協議,否則動態載入驅動模組時,報錯+MODULE_LICENSE("GPL");


三、BSP部分

下面摘錄BSP中涉及到的BMA220相關部分:

/***********************************************************//************************* 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();}

四. 添加驅動到核心

1. 先在driver/misc/目錄下建立sensors目錄
2. 在/driver/misc/Kconfig末尾添加一行:

source "drivers/misc/sensors/Kconfig"

3. 在/driver/misc/Makefile末尾添加一行:

obj-y+= sensors/

4. 在/driver/misc/sensors/目錄下添加5個檔案:
bma220.c bma220.h bma220_driver.c Kconfig Makefile

其中,bma220_driver.c為上面修改過的,bma220.c bma220.h為原始代碼。

/driver/misc/sensors/目錄下的Kconfig和Makefile的內容如下,其中Kconfig中第一項用於配置BMA220裝置驅動,第二項用於配置晶片1腳在產品正面的相對位置。

## 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

在bma220_driver.c用到了這個配置,如下:

/* * 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;}


配置介面如下:

最後,產生的.config裡包含的相關配置如下,其中第三項的值就被上述函數編譯時間使用。

CONFIG_SENSORS_DEVICES=yCONFIG_INPUT_BMA220=mCONFIG_INPUT_BMA220_POSITION=0

五、測試用應用程式

應用程式主要還是配置BMA220_SET_SUSPEND為1(預設為0,讀到的資料始終不變)。板子在機殼上是背面朝上,故測試結果是,板子正面朝上,Z軸值為達到負數最小值,背面朝上Z軸值為正數最大值。板子橫向立起來,X軸整數最大值。板子縱向立起來,Y軸整數最大值。測試結果表明,驅動正常。

#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;}







聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.