在Android 2.3(Gingerbread) 系统的时候,我写过一篇关于“Android 震动马达系统“的文章,当时的Linux内核还是2.6版本的。写那篇文章的目的,是想彻底的了解从硬件到驱动,再到应用的运作流程。完成了之后,文章一直仍在草稿箱里面没发表;今天看到,决定整理一下,重新发表。目的是想和大家分享自己对Android系统的一点认识:以马达为代表,来考究“Android是如何一步步工作的。它从硬件设计,到Linux驱动,再到HAL,再到JNI,再到Framework,最后到被应用调用,这整套的流程到底是怎么样的!

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3404808.html

Part 1 马达的硬件设计

    马达的震动原理很简单,给马达通电,马达就能震动。至于马达是如何工作,如何将电能转化为机械能,这不是我们关心的重点。但是,我们要需要了解如何控制马达的通电。在硬件上,我们是通过一个IO口(GPIO)去控制;对于马达而言,我们可以将IO理解为一个开关。当开关合上时,马达震动;开关断开,马达停止震动。

    GPIO(General Purpose Input Output),称为通用输入/输出。它可以被配置为中断、输入、输出等类型,从而对各个IO进行控制。对于马达而已,GPIO就相当于一个开关。下面看看硬件原理图中的马达部分,如下图:

Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
 

注:上面原理图对应CPU是“三星A8”。不同平台的马达,马达的接法和GPIO都不一样;但原理都是类似的。

原理图中红线标注部分的含义:GPH3_3是马达的GPIO。三星A8中有很多组GPIO,而马达对应和GPH3_3连接。

 

Part 2 马达的驱动代码

    知道马达的硬件设计之后,我们就可以进行Linux Driver开发工作,也就是编写马达的驱动。Linux的一个非常重要的特点,一切都是文件!而我们进行Linux Driver开发的目的,就是将硬件设备映射成一个文件;然后,我们可以通过操作文件,来操作对应的硬件设备。

    OK!理解了驱动的作用和原理之后,我们接下来开发讲解马达的驱动开发。

 

1. Datasheet中相关信息

    我们知道,马达是通过GPIO去控制;接下来,我们就是找到马达对应的GPIO信息,然后控制该GPIO即可。

    通过马达的原理图,我们知道马达和GPH3_3相连接。我们查阅“三星A8 的Datasheet”,查找GPH3_3的相关信息。

   所谓Datasheet,就是CPU芯片的数据手册。
   上面记载了CPU的功能特性和操作方式等信息。任何一个厂家在发布它的芯片时,都会提供对应的Datasheet给它的客户;客户根据Datasheet上面所描述的CPU的特性,就可以进行相关的开发(当然,实际开发中可能还需要芯片厂商的支持)。例如,国内手机都是采用MTK平台,对于MTK方案开发商来说,它要开发MTK6577的产品。那么首先,MTK原厂会提供一份MTK6577的BSP包,BSP包中包括了MTK6577的Datasheet,也就是该芯片的数据手册。方案开发商有任何关于MTK6577的问题,都可以查阅该Datasheet。
    三星A8的Datasheet中,关于GPH3_3的信息如下:
Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)

说明

(01) GPH3_3对应CPU中的寄存器是GPH3CON[3]。

(02) [15:12] 表示寄存器的第12~15位,一个寄存器共32 bits。而第三列的 0000, 0001, 0010, 0011, 1111表示“寄存器取不同值的时候,该GPIO的功能”。

例如, 0000表示将该GPIO作为输入,0001表示将GPIO作为输出,1111表示将该GPIO作为中断。

           前面,我们已经说过,操作马达就是相当与将它作为一个开关操作。因此,我们需要将马达的GPIO设为“输入”类型;然后输入1,相当于开启马达;输入0,则是关闭马达!

 

下面,我们需要做的就是在Driver中将GPH3_3(也就是GPH3CON[3])映射为一个文件节点,并将它配置为“输入”类型,即将GPH3CON[3]的寄存器值设为0000。

 

2. 马达的驱动

    我们编写马达驱动(drivers/misc/misc_sysfs.c),将马达(vibrator)注册道platform总线上。源码如下:

  1 #include <linux/kernel.h>
  2 #include <linux/types.h>
  3 #include <linux/module.h>
  4 #include <linux/device.h>
  5 #include <linux/platform_device.h>
  6 #include <linux/delay.h>
  7 #include <linux/irq.h>
  8 #include <linux/interrupt.h>
  9 #include <linux/sysfs.h>
 10 #include <linux/input.h>
 11 #include <mach/gpio.h>
 12 
 13 // vibrator 对应的GPIO
 14 #define  VIBRATOR_POWER_PORT (S5PV210_GPH3(3))
 15 
 16 typedef struct combo_module__t    {
 17     unsigned char            status_vibrator;
 18 }    combo_module_t    ;
 19 
 20 static combo_module_t combo_module;
 21 
 22 /*
 23  * vibrator初始化函数:申请GPIO,并初始化vibrator状态。
 24  */
 25 static void combo_module_init(void)
 26 {
 27     if(gpio_request(VIBRATOR_POWER_PORT, "vibrator power"))    {
 28         printk("misc_sysfs.c request vibrator gpio failse.\n");
 29     }
 30     gpio_pull_updown(VIBRATOR_POWER_PORT, PullDisable);
 31       gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW);    
 32 
 33     combo_module.status_vibrator  = 0;
 34 }
 35 
 36 /*
 37  * vibrator控制函数
 38  */
 39 staticvoid combo_module_control(void)
 40 {
 41     if(combo_module.status_vibrator)
 42     {
 43         gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_HIGH);
 44     }
 45     else    
 46     {
 47         gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW);
 48     }
 49 
 50 }
 51 
 52 
 53 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 54 
 55 static ssize_t show_vibrator_onoff (struct device *dev, struct device_attribute *attr, char *buf)
 56 {
 57     return    sprintf(buf, "%d\n", combo_module.status_vibrator);
 58 }
 59 
 60 static ssize_t set_vibrator_onoff (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 61 {
 62      unsigned int    val;
 63 
 64     if(!(sscanf(buf, "%u\n", &val)))     return    -EINVAL;
 65 
 66     //printk("set_vibrator_onoff:%d\n",val);
 67 
 68     if(!val )    
 69     {
 70         combo_module.status_vibrator = 0;
 71         combo_module_control();
 72     }
 73     else        
 74     {
 75         combo_module.status_vibrator = 1;
 76         combo_module_control();
 77 
 78         msleep(val);
 79 
 80         combo_module.status_vibrator = 0;
 81         combo_module_control();
 82     }
 83     
 84     return count;
 85 }
 86 
 87 static    ssize_t show_vibrator_onoff    (struct device *dev, struct device_attribute *attr, char *buf);
 88 static     ssize_t set_vibrator_onoff    (struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
 89 // 将vibrator注册到sysfs文件系统。
 90 // 参数说明:
 91 //       vibrator_onoff      : vibrator对应在sysfs下的文件节点名称
 92 //       S_IRWXUGO           : 文件节点的属性
 93 //       show_vibrator_onoff : 对应的读函数
 94 //       set_vibrator_onoff  : 对应的写函数
 95 static DEVICE_ATTR(vibrator_onoff, S_IRWXUGO, show_vibrator_onoff, set_vibrator_onoff);
 96 
 97 
 98 static struct attribute *control_sysfs_entries[] = {
 99     &dev_attr_vibrator_onoff.attr,
100     NULL
101 };
102 
103 static struct attribute_group control_sysfs_attr_group = {
104     .name   = NULL,
105     .attrs  = control_sysfs_entries,
106 };
107 
108 static int control_sysfs_probe(struct platform_device *pdev)    
109 {
110     printk("vibrator probe");
111     combo_module_init();
112     combo_module_control();
113     return    sysfs_create_group(&pdev->dev.kobj, &control_sysfs_attr_group);
114 }
115 
116 staticint control_sysfs_remove(struct platform_device *pdev)    
117 {
118     sysfs_remove_group(&pdev->dev.kobj, &control_sysfs_attr_group);
119     
120     return    0;
121 }
122 
123 #ifdef CONFIG_PM
124 static int control_sysfs_resume(struct platform_device *dev)
125 {
126 
127     combo_module_control();
128 
129     return  0;
130 }
131 
132 static int control_sysfs_suspend(struct platform_device *dev, pm_message_t state)
133 {
134     
135     combo_module_control();
136     
137     return  0;
138 }
139 #else
140 #define control_sysfs_suspend NULL
141 #define control_sysfs_resume NULL
142 #endif
143 
144 
145 static struct platform_driver control_sysfs_driver = {
146     .driver = {
147         .name = "misc_ctl",
148         .owner = THIS_MODULE,
149     },
150     .probe         = control_sysfs_probe,
151     .remove     = control_sysfs_remove,
152     .suspend    = control_sysfs_suspend,
153     .resume        = control_sysfs_resume,
154 };
155 
156 static int __init control_sysfs_init(void)
157 {    
158     // 将vibrator注册到platform总线
159     printk("vibrator init");
160     return platform_driver_register(&control_sysfs_driver);
161 }
162 
163 static void __exit control_sysfs_exit(void)
164 {
165    platform_driver_unregister(&control_sysfs_driver);
166 }
167 
168 
169 module_init(control_sysfs_init);
170 module_exit(control_sysfs_exit);
171 
172 
173 MODULE_DESCRIPTION("misc control driver");
174 MODULE_AUTHOR("other");
175 MODULE_LICENSE("GPL");
View Code

相关文章: