博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于TINY4412的Andorid开发-------简单的LED灯控制
阅读量:7118 次
发布时间:2019-06-28

本文共 22971 字,大约阅读时间需要 76 分钟。

参考资料:

《Andriod系统源代码情景分析》

《嵌入式Linux系统开发完全手册_基于4412_上册》

 

 

作者:彭东林

邮箱:

 

 

平台介绍:

主机:Win7 32位

虚拟机:VMware10 + ubuntu-12.04.2-desktop-amd64

Android版本:  android-4.2.2_r1

Linux内核版本:linux-3.5.0

Bootloader:  友善之臂提供的Superboot4412.bin

目标平台:tiny4412ADK+S700 4GB Flash

 

目的: 在Tiny4412上运行的Android系统上,通过点击屏幕上的Button来控制Tiny4412的核心板上的四个LED灯的亮灭。一个有八个Button,每个灯的亮灭通过两个灯来控制,点击ON,相应的LED亮;点击OFF,相应的LED灯灭。

 

下面分几步完成:

1、编写驱动程序

2、测试驱动程序

3、编写HAL代码

4、编写framework代码

5、编写JNI代码

6、编写App

下面开始:

一、编写驱动程序

分析tiny4412的原理图,看一下LED灯的位置:

可以知道,LED是低电平亮,高电平灭。

看一下,接到了Exynos4412的哪些引脚上了:

可以看到:

LED1  --------- GPM4_0

LED2  --------- GPM4_1

LED3  --------- GPM4_2

LED4  --------- GPM4_3

看一下Exynos4412的芯片手册,看一下GPM4的相关寄存器:

图中第二列表示的相对于基地址的偏移量,这里基地址是:0x11000000.

在芯片手册的Page288 ~ Page291对这些寄存器有更详细的介绍。

以GPM4_0引脚为例:

为了控制灯,[3:0]应设置为0x01,即输出模式

向GPM4DAT的第0位写0,GPM4_0引脚输出低电平,LED1亮;

向GPM4DAT的第0位写1,GPM4_0引脚输出高电平,LED1灭;

接下来,开始写驱动程序,用友善之臂自带的Linux3.5.0内核

1:  cd linux-3.5/
2:  cd drivers/
3:  mkdir android_led
4:  cd android_led/

在android_led/下创建led_demo.c和led_demo.h文件:

touch  led_demo.c led_demo.h

再在其中创建Makefile和Kconfig文件

touch Makefile Kconfig
  • 修改Kconfig:
1:  config LED_DEMO
2:      tristate "Android Led Demo"
3:      default n
4:      help
5:      This is the led demo for Android system.
  • 修改Makefile:
obj-$(CONFIG_LED_DEMO) += led_demo.o
  • 修改drivers/Kconfig,添加 source “drivers/android_led/Kconfig”
1:  menu "Device Drivers"
2:   
3:  source "drivers/android_led/Kconfig"
4:   
5:  ......
6:   
7:  endmenu
  • 修改drivers/Makefile:
1:  ......
2:   
3:  obj-$(CONFIG_LED_DEMO)  += android_led/
  • 在内核顶层目录下执行make  menuconfig,进入Device Drivers,将 Android Led Demo选择为*,然后保存配置退出。

 

注:执行上面这些操作之前,确保已经按照友善之臂的手册,成功编译了Android上用的Linux内核,并且在arch/arm/boot下生成了zImage等文件。

在前期开发的时候,时不时要编译,可以将drivers/android_led/Makefile修改为:

1:  #obj-$(CONFIG_LED_DEMO) += led_demo.o
2:  obj-m += led_demo.o

编译的时候,可以使用:

make M=drivers/android_led modules

目的是提高编译速度,最后再将Makfile改回原样。临时测试,可以在Wind7的命令行下,使用adb push将led_demo.ko上传到/data/local下,然后用adb shell登陆板子,进行测试。

  • 修改led_demo.h和led_demo.c

led_demo.h

1:  #ifndef __LED_DEMO_H__
2:  #define __LED_DEMO_H__
3:   
4:  #include 
5:   
6:  #define LED_ON    _IOW('L', 0, int)
7:  #define LED_OFF    _IOW('L', 1, int)
8:   
9:  #define LED_DEMO_DEVICE_NODE_NAME  "led_demo"
10:  #define LED_DEMO_DEVICE_CLASS_NAME "led_demo"
11:  #define LED_DEMO_DEVICE_FILE_NAME  "led_demo"
12:   
13:  #define EXYNOS4412_GPM4CON    0x110002E0
14:  #define EXYNOS4412_GPM4DAT    0x110002E4
15:   
16:   
17:  struct led_demo_dev
18:  {
19:      struct cdev dev;
20:  };
21:   
22:  #endif

 

led_demo.c

1:  #include 
2:  #include 
3:  #include 
4:  #include 
5:  #include 
6:   
7:  #include 
8:  #include 
9:   
10:   
11:  #include "led_demo.h"
12:   
13:   
14:  MODULE_LICENSE("GPL");
15:   
16:   
17:  static int led_demo_major;
18:  static int led_demo_minor;
19:  static int number_of_dev = 1;
20:   
21:  static struct led_demo_dev  *led_dev = NULL;
22:   
23:  static unsigned int *GPM4CON = NULL;
24:  static unsigned int *GPM4DAT = NULL;
25:   
26:  static struct class *led_demo_class = NULL;
27:   
28:   
29:  static int led_open (struct inode *node, struct file *fops)
30:  {
31:      struct led_demo_dev *dev;
32:   
33:      dev = container_of(node->i_cdev, struct led_demo_dev, dev);
34:   
35:      fops->private_data = dev;
36:   
37:      return 0;
38:  }
39:  static int led_close (struct inode *node, struct file *fops)
40:  {
41:      return 0;
42:  }
43:   
44:  static long led_ioctl (struct file *fops, unsigned int cmd, unsigned long data)
45:  {
46:      //struct led_demo_dev * led_dev = (struct led_demo_dev *)fops->private_data;
47:   
48:      if((data < 1) || (data > 4))
49:      {
50:          printk(KERN_ALERT"parameter is no valid.\n");
51:          return -EINVAL;
52:      }
53:
54:      switch (cmd)
55:      {
56:          case LED_OFF:
57:              writel(readl(GPM4DAT) | (0x1<<(data-1)), GPM4DAT);
58:              break;
59:          case LED_ON:
60:              writel(readl(GPM4DAT) & ~(0x1<<(data-1)), GPM4DAT);
61:              break;
62:          default:
63:              return -EINVAL;
64:              break;
65:      }
66:   
67:
68:      return 0;
69:  }
70:   
71:  struct file_operations led_fops =
72:  {
73:      .owner = THIS_MODULE,
74:      .open = led_open,
75:      .unlocked_ioctl = led_ioctl,
76:      .compat_ioctl = led_ioctl,
77:      .release = led_close,
78:  };
79:   
80:  static int __led_setup_dev(struct led_demo_dev * dev)
81:  {
82:      int err = -1;
83:   
84:      dev_t devno = MKDEV(led_demo_major, led_demo_minor);
85:   
86:      memset(dev, 0, sizeof(struct led_demo_dev));
87:   
88:      cdev_init(&(dev->dev), &led_fops);
89:   
90:      dev->dev.owner = THIS_MODULE;
91:   
92:      err = cdev_add(&(dev->dev), devno, number_of_dev);
93:      if(err < 0)
94:      {
95:          return err;
96:      }
97:
98:      return 0;
99:  }
100:   
101:  static int led_demo_init(void)
102:  {
103:      int err = -1;
104:      dev_t dev;
105:      struct device *temp = NULL;
106:   
107:      printk(KERN_ALERT"Initializing led demo device.\n");
108:   
109:      err = alloc_chrdev_region(&dev, 0, number_of_dev, LED_DEMO_DEVICE_NODE_NAME);
110:      if(err < 0)
111:      {
112:          printk(KERN_ALERT"fail to alloc char dev region.\n");
113:          goto fail;
114:      }
115:   
116:      led_demo_major = MAJOR(dev);
117:      led_demo_minor = MINOR(dev);
118:   
119:      led_dev = kmalloc(sizeof(struct led_demo_dev), GFP_KERNEL);
120:      if(!led_dev)
121:      {
122:          err = -ENOMEM;
123:          printk(KERN_ALERT"Failed to alloc led device.\n");
124:          goto unregister;
125:      }
126:   
127:      err = __led_setup_dev(led_dev);
128:      if (err < 0)
129:      {
130:          printk(KERN_ALERT"Failed to setup led device.\n");
131:          goto clean_up;
132:      }
133:   
134:      GPM4CON = (unsigned int *)ioremap(EXYNOS4412_GPM4CON, 4);
135:      if(!GPM4CON)
136:      {
137:          err = -ENOMEM;
138:          goto destroy_cdev;
139:      }
140:
141:      GPM4DAT = (unsigned int *)ioremap(EXYNOS4412_GPM4DAT, 4);
142:      if(!GPM4DAT)
143:      {
144:          err = -ENOMEM;
145:          goto unmap1;
146:      }
147:   
148:      writel((readl(GPM4CON) & ~0xffff) | 0x1111, GPM4CON);
149:      writel(readl(GPM4DAT)| 0xf, GPM4DAT);
150:   
151:      led_demo_class = class_create(THIS_MODULE, LED_DEMO_DEVICE_CLASS_NAME);
152:      if(IS_ERR(led_demo_class))
153:      {
154:          err = PTR_ERR(led_demo_class);
155:          printk(KERN_ALERT"Failed to create led demo class.\n");
156:          goto unmap2;
157:      }
158:   
159:      temp = device_create(led_demo_class, NULL, dev, NULL, "%s", LED_DEMO_DEVICE_FILE_NAME);
160:      if(IS_ERR(temp))
161:      {
162:          err = PTR_ERR(temp);
163:          printk(KERN_ALERT"Failed to create led demo device.\n");
164:          goto destroy_class;
165:      }
166:   
167:      dev_set_drvdata(temp, (void *)led_dev);
168:   
169:      printk(KERN_ALERT"Succeed to initialize led demo device.\n");
170:
171:      return 0;
172:   
173:  destroy_class:
174:      class_destroy(led_demo_class);
175:
176:  unmap2:
177:      iounmap(GPM4DAT);
178:
179:  unmap1:
180:      iounmap(GPM4CON);
181:
182:  destroy_cdev:
183:      cdev_del(&(led_dev->dev));
184:   
185:  clean_up:
186:      kfree(led_dev);
187:
188:  unregister:
189:      unregister_chrdev_region(MKDEV(led_demo_major, led_demo_minor), number_of_dev);
190:
191:  fail:
192:   
193:      return err;
194:  }
195:   
196:  static void led_demo_exit(void)
197:  {
198:      if(led_demo_class)
199:      {
200:          device_destroy(led_demo_class, MKDEV(led_demo_major, led_demo_minor));
201:          class_destroy(led_demo_class);
202:      }
203:
204:      iounmap(GPM4DAT);
205:      iounmap(GPM4CON);
206:   
207:      if(led_dev)
208:      {
209:          cdev_del(&(led_dev->dev));
210:          kfree(led_dev);
211:      }
212:   
213:      unregister_chrdev_region(MKDEV(led_demo_major, led_demo_minor), number_of_dev);
214:  }
215:   
216:   
217:   
218:  module_init(led_demo_init);
219:  module_exit(led_demo_exit);
220:   

 

编写完成后,在内核源码的顶层目录执行make zImage –jN,然后就会在arch/arm/boot/生成zImage文件,利用友善之臂提供的Minitools将zImage烧写到板子上。具体步骤,参考友善之臂提供的PDF文档:《Tiny4412用户手册》

二、编写代码测试驱动程序

在android-4.2.2_r1源码顶层目录下

1:  external/led_demo/
2:  ├── Android.mk
3:  ├── led_demo.c
4:  └── led_demo.h

即,在external/下创建led_demo目录,并在其中创建Android.mk、led_demo.c以及led_demo.h文件.

Android.mk:

1:  LOCAL_PATH:= $(call my-dir)
2:  include $(CLEAR_VARS)
3:  LOCAL_MODULE_TAGS := optional
4:  LOCAL_SRC_FILES := $(call all-subdir-c-files)
5:  LOCAL_MODULE := led_demo_test
6:  include $(BUILD_EXECUTABLE)
7:   

led_demo.h:

1:  #ifndef __LED_DEMO_H__
2:  #define __LED_DEMO_H__
3:   
4:  #define LED_ON    _IOW('L', 0, int)
5:  #define LED_OFF    _IOW('L', 1, int)
6:   
7:  #endif

led_demo.c:

1:  #include 
2:  #include 
3:  #include 
4:  #include 
5:  #include 
6:  #include 
7:   
8:  #include "led_demo.h"
9:   
10:  int main(int argc, const char *argv[])
11:  {
12:      int fd;
13:      int i;
14:   
15:      fd = open("/dev/led_demo", O_RDWR);
16:      if (fd < 0)
17:      {
18:          perror("failed to open.\n");
19:          exit(-1);
20:      }
21:   
22:      while(1)
23:      {
24:          for(i=0; i<4; i++)
25:          {
26:              ioctl(fd, LED_OFF, i+1);
27:              sleep(1);
28:              ioctl(fd, LED_ON, i+1);
29:              sleep(1);
30:              ioctl(fd, LED_OFF, i+1);
31:              sleep(1);
32:          }
33:      }
34:   
35:      close(fd);
36:   
37:      return 0;
38:  }

编写完成后,在android-4.2.2_r1源码顶层目录下执行:

1:    mmm ./external/led_demo/
2:   
3:   ./gen-img.sh

然后将顶层目录下新生成的system.img利用友善之臂提供的Minitools烧写到板子上。

烧写完成后,重启板子。

使用串口终端登陆板子,使用su命令进入root用户模式,然后进入/system/bin目录下,执行./led_demo_test,观察现象,可以看到,TINY4412的核心板上的四个LED灯循环亮灭。也可以使用wind7下的控制终端,用adb shell登陆板子,进行测试。

三、编写HAL代码

在hardware/libhardware/include/hardware/下创建文件led_demo_hal.h

在hardware/libhardware/modules/下创建目录led_demo_hal,然后进入led_demo_hal,创建两个文件,分别是Android.mk和

led_demo_hal.cpp。

下面是文件内容:

hardware/libhardware/include/hardware/led_demo_hal.h

1:  #ifndef ANDROID_LED_DEMO_HAL_H
2:  #define ANDROID_LED_DEMO_HAL_H
3:   
4:  #include 
5:   
6:  __BEGIN_DECLS
7:   
8:  #define LED_DEMO_HARDWARE_MODULE_ID   "led_demo_hal"  //模块ID 需要与下面的Android.mk中的LOCAL_MODULE 匹配,否则无法加载该HAL模块
9:  #define LED_DEMO_HARDWARE_DEVICE_ID   "led_demo"      // 设备ID
10:   
11:   
12:  struct led_demo_module_t
13:  {
14:          struct hw_module_t common;
15:  };
16:   
17:  struct led_demo_device_t
18:  {
19:          struct hw_device_t common;
20:          int fd;
21:          int (*set_on)(struct led_demo_device_t *dev, int val);  //用于控制LED,点亮第val个LED灯
22:          int (*set_off)(struct led_demo_device_t *dev, int val); //熄灭第val个LED灯
23:  };
24:   
25:  __END_DECLS
26:   
27:   
28:  #endif

 

hardware/libhardware/modules/led_demo_hal/led_demo_hal.cpp

1:  #define LOG_TAG "LED_DEMO_HALSTUB"   //将来可以用DDMS的LogCat工具进行调试,便于查看打印信息
2:   
3:  #include 
4:  #include 
5:   
6:  #include 
7:  #include 
8:   
9:  #include 
10:  #include 
11:   
12:   
13:  #define DEVICE_NAME    "/dev/led_demo"    //设备结点,有Linux驱动程序自动创建
14:  #define MODULE_NAME    "led_demo"
15:  #define MODULE_AUTHOR  "pengdonglin137@163.com"
16:   
17:  #define LED_ON  0x40044c00     //点灯的命令,其实就是_IOW('L', 0, int)的值,_IOW在编译时无法识别,待以后解决
18:  #define LED_OFF 0x40044c01     //灭灯命令,其实就是_IOW('L', 1, int)的值,可以在上面的led_demo.c中加打印,看一下这个值是多少
19:   
20:   
21:  static int led_demo_open(const struct hw_module_t* module, const char* id,
22:          struct hw_device_t** device);
23:   
24:  static int led_demo_close(struct hw_device_t* device);
25:   
26:  static int led_demo_set_on(struct led_demo_device_t *dev, int val);
27:   
28:  static int led_demo_set_off(struct led_demo_device_t *dev, int val);
29:   
30:   
31:  static hw_module_methods_t led_demo_module_methods =
32:  {
33:      open:led_demo_open,
34:  };
35:   
36:  struct led_demo_module_t HAL_MODULE_INFO_SYM =
37:  {
38:      common:{
39:          tag:HARDWARE_MODULE_TAG,
40:          version_major:1,
41:          version_minor:0,
42:          id:LED_DEMO_HARDWARE_MODULE_ID,
43:          name:MODULE_NAME,
44:          author:MODULE_AUTHOR,
45:          methods:&led_demo_module_methods,
46:      }
47:  };
48:   
49:  static int led_demo_open(const struct hw_module_t* module, const char* id,
50:          struct hw_device_t** device)
51:  {
52:      if(!strcmp(id, LED_DEMO_HARDWARE_DEVICE_ID))
53:      {
54:          struct led_demo_device_t *dev;
55:   
56:          dev = (struct led_demo_device_t *)malloc(sizeof(struct led_demo_device_t));
57:          if(!dev)
58:          {
59:              ALOGE("Failed to alloc space for struct led_demo_device_t.");
60:              return -EFAULT;
61:          }
62:   
63:          memset(dev, 0, sizeof(struct led_demo_device_t));
64:   
65:          dev->common.tag =
HARDWARE_DEVICE_TAG
;
66:          dev->common.version = 0;
67:          dev->common.module = (struct hw_module_t *)module;
68:          dev->common.close = led_demo_close;
69:          dev->set_on = led_demo_set_on;
70:          dev->set_off = led_demo_set_off;
71:   
72:          if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1)
73:          {
74:              ALOGE("Failed to open device %s ---- %s\n.", DEVICE_NAME, strerror(errno));
75:              free(dev);
76:              return -EFAULT;
77:          }
78:   
79:          *device = &(dev->common);
80:   
81:          ALOGE("Open device file %s successfully.", DEVICE_NAME);
82:   
83:      }
84:   
85:      return -EFAULT;
86:  }
87:   
88:  static int led_demo_close(struct hw_device_t* device)
89:  {
90:      struct led_demo_device_t *led_device = (struct led_demo_device_t *)device;
91:      if(led_device)
92:      {
93:          close(led_device->fd);
94:          free(led_device);
95:      }
96:   
97:      return 0;
98:  }
99:   
100:  static int led_demo_set_on(struct led_demo_device_t *dev, int val)
101:  {
102:      if(!dev)
103:      {
104:          ALOGE("Null dev pointer.");
105:          return -EFAULT;
106:      }
107:
108:      if(ioctl(dev->fd, LED_ON, val) < 0)
109:      {
110:          ALOGE("ioctl error --- %s.", strerror(errno));
111:          return -EFAULT;
112:      }
113:   
114:      return 0;
115:
116:  }
117:   
118:  static int led_demo_set_off(struct led_demo_device_t *dev, int val)
119:  {
120:      if(!dev)
121:      {
122:          ALOGE("Null dev pointer.");
123:          return -EFAULT;
124:      }
125:
126:      if(ioctl(dev->fd, LED_OFF, val) < 0)
127:      {
128:          ALOGE("ioctl error --- %s.", strerror(errno));
129:          return -EFAULT;
130:      }
131:
132:      return 0;
133:
134:  }
135:   

 

hardware/libhardware/modules/led_demo_hal/Android.mk

1:  LOCAL_PATH := $(call my-dir)
2:  include $(CLEAR_VARS)
3:  LOCAL_MODULE_TAGS := optional
4:  LOCAL_PRELINK_MODULE := false
5:  LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
6:  LOCAL_SHARED_LIBRARIES := liblog
7:  LOCAL_SRC_FILES := led_demo_hal.cpp
8:  LOCAL_MODULE := led_demo_hal.default
9:  include $(BUILD_SHARED_LIBRARY)

 

编写完成后,在Android源码的顶层目录执行:

mmm ./hardware/libhardware/modules/led_demo_hal/

最终out/target/product/tiny4412/system/lib/hw/目录下得到一个led_demo_hal.default.so文件。

下面处理一下硬件设备访问权限问题

在硬件抽象层模块中,我们是调用open函数来打开对应的设备文件的,在默认情况下,只有root用户才有权限访问系统的设备文件。但是一般的应用程序是没有root用户权限的。

解决办法,赋予root之外的其他用户访问设别文件/dev/led_demo的权限。做法如下:

在Android源码顶层目录下,修改system/core/rootdir/ueventd.rc,添加如下内容:

/dev/led_demo             0666   root       root

修改了ueventd.rc文件后,需要重新编译Android源代码工程,编译时,文件system/core/rootdir/ueventd.rc会拷贝到out/target/product/tiny4412/root/下,并且最终打包在ramdisk.img中。对于友善之臂,执行完make -jN后,还需要执行./gen-img.sh脚本,然后在Android源码顶层目录中会生成ramdisk-u.img文件,利用MiniTools将其烧写到板子上。

四、编写Framework代码

  • 定义硬件访问服务接口

在frameworks/base/core/java/android/os/创建文件ILed_demo_service.aidl,内容如下:

1:  package android.os;
2:   
3:  interface ILed_demo_service
4:  {
5:      void led_set_ON(int val);
6:      void led_set_OFF(int val);
7:  }

然后,修改frameworks/base/Android.mk

1:  LOCAL_SRC_FILES += \
2:      ......
3:      core/java/android/os/IVibratorService.aidl \
4:      core/java/android/os/ILed_demo_service.aidl \

最后,在Android源码顶层目录下执行

mmm ./frameworks/base/

编译后得到的framework.jar文件就包含了ILed_demo_service接口。

  • 实现硬件访问服务

在frameworks/base/services/java/com/android/server/创建文件Led_demo_Service.java,内容如下:

1:  package com.android.server;
2:  import android.content.Context;
3:  import android.os.ILed_demo_service;
4:  import android.util.Slog;
5:   
6:   
7:  public class Led_demo_Service extends ILed_demo_service.Stub
8:  {
9:          private static final String TAG = "Led_demo_Service";  //方便DDMS提供的LogCat工具看打印信息
10:   
11:          private int mPtr = 0;
12:   
13:          Led_demo_Service()
14:          {
15:                  mPtr = init_native();  //硬件访问服务Led_demo_Service在启动时,会通过JNI方法init_native
16:   
17:                  if(mPtr == 0)
18:                  {
19:                          Slog.e(TAG, "Failed to initialize Led demo Service.");
20:                  }
21:          }
22:   
23:          public void led_set_ON(int val)
24:          {
25:                  if(mPtr == 0)
26:                  {
27:                          Slog.e(TAG, "Led demo Service is not initialized.");
28:                          return;
29:                  }
30:   
31:                  set_ON_native(mPtr, val);
32:          }
33:   
34:          public void led_set_OFF(int val)
35:          {
36:                  if(mPtr == 0)
37:                  {
38:                          Slog.e(TAG, "Led demo Service is not initialized.");
39:                          return;
40:                  }
41:   
42:                  set_OFF_native(mPtr, val);
43:          }
44:   
45:   
46:          private static native int init_native();
47:          private static native void set_OFF_native(int mPtr, int val);
48:          private static native void set_ON_native(int mPtr, int val);
49:   
50:   
51:  };

编写完成后,在Android源码顶层目录下执行:

mmm ./frameworks/base/services/java/

编译后得到的services.jar文件就包含有Led_demo_Service类。

 

五、编写JNI代码

在frameworks/base/services/jni/下创建文件com_android_server_led_demo_service.cpp,内容如下:

1:  #define LOG_TAG  "LED_DEMO_Service_JNI"   //方便LogCat调试工具查看打印信息
2:   
3:  #include "jni.h"
4:  #include "JNIHelp.h"
5:  #include "android_runtime/AndroidRuntime.h"
6:   
7:  #include 
8:  #include 
9:  #include 
10:  #include 
11:   
12:  #include 
13:   
14:   
15:  namespace android
16:  {
17:   
18:      static void led_demo_setOFF(JNIEnv *env, jobject clazz, jint ptr, jint value)
19:      {
20:          led_demo_device_t *device = (led_demo_device_t *)ptr;
21:          if(!device)
22:          {
23:              ALOGE("Device led demo is not open.");
24:              return ;
25:          }
26:   
27:          int val = value;
28:   
29:          ALOGI("Set value %d to device led demo.", val);
30:   
31:          device->set_off(device, value);
32:      }
33:   
34:      static void led_demo_setON(JNIEnv *env, jobject clazz, jint ptr, jint value)
35:      {
36:          led_demo_device_t *device = (led_demo_device_t *)ptr;
37:          if(!device)
38:          {
39:              ALOGE("Device led demo is not open.");
40:              return ;
41:          }
42:   
43:          int val = value;
44:   
45:          ALOGI("Set value %d to device led demo.", val);
46:   
47:          device->set_on(device, value);
48:      }
49:
50:   
51:      static inline int led_demo_device_open(const hw_module_t *module, struct led_demo_device_t **device)
52:      {
53:          return module->methods->open(module, LED_DEMO_HARDWARE_DEVICE_ID, (struct hw_device_t **)device);
54:      }
55:   
56:   
57:   
58:      static jint led_demo_init(JNIEnv *env, jclass clazz)
59:      {
60:          struct led_demo_module_t *module;
61:          struct led_demo_device_t *device;
62:   
63:   
64:          ALOGI("Initializing HAL stub led ......");
65:   
66:          if(hw_get_module(
LED_DEMO_HARDWARE_MODULE_ID
, (const struct hw_module_t **)&module) == 0)
67:          {
68:              ALOGE("Device led demo found.");
69:   
70:              if(led_demo_device_open(&(module->common), &device))
71:              {
72:                  ALOGI("Device led demo is open.");
73:                  return (jint)device;
74:              }
75:   
76:              ALOGE("Failed to open device led.");
77:   
78:              return 0;
79:          }
80:   
81:          ALOGE("Failed to get HAL stub led demo.");
82:          return 0;
83:      }
84:   
85:      static const JNINativeMethod  method_table[] =
86:      {
87:          {
"init_native", "()I", (void *)led_demo_init},
88:          {
"set_OFF_native", "(II)V", (void *)led_demo_setOFF},
89:          {
"set_ON_native", "(II)V", (void *)led_demo_setON},
90:      };
91:   
92:      int register_android_server_led_demo_service(JNIEnv *env)
93:      {
94:          return jniRegisterNativeMethods(env, "com/android/server/Led_demo_Service",
95:              method_table, NELEM(method_table));
96:      }
97:   
98:  };
99:   
100:   

 

修改frameworks/base/services/jni/onload.cpp文件:

1:  namespace android {
2:  ......
3:  int register_android_server_led_demo_service(JNIEnv *env);
4:  };
5:   
6:  extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
7:  {
8:      ......
9:      register_android_server_led_demo_service(env);
10:   
11:      return JNI_VERSION_1_4;
12:  }

 

修改frameworks/base/services/jni/Android.mk文件,内容如下:

1:  LOCAL_SRC_FILES:= \
2:      ......
3:      com_android_server_led_demo_service.cpp \
4:      onload.cpp

最后,在Android源码顶层目录下执行:

mmm ./frameworks/base/services/jni/
  • 启动硬件服务

修改frameworks/base/services/java/com/android/server/SystemServer.java文件

1:  // Bring up services needed for UI.
2:  if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
3:  ......
4:  try{
5:      Slog.i(TAG, "Led demo Service");
6:      ServiceManager.addService("led_demo", new Led_demo_Service());  //这里的名字要跟App中getService时传入的参数相同
7:  } catch (Throwable e) {
8:      Slog.e(TAG, "Failed to start Led demo Service", e);
9:  }
10:   
11:  }

 

编写完成后,在Android源码顶层目录下执行:

mmm ./frameworks/base/services/java/

六、编写App

这个app是在Win7下用eclipse开发的,如下图:

 

上面的错误是因为Win7下的SDK开发包中并没有我们编写的ILed_demo_service,这个不要紧。导出方法:在工程Tiny4412_led_demo上右键单击,点击Export,选择General----> File System ,选择导出路径,最后点击Finish。将导出的工程Tiny4412_led_demo拷贝到packages/experimental/目录下,然后进入packages/experimental/Tiny4412_led_demo,在其中创建一个Android.mk文件:

1:  LOCAL_PATH:= $(call my-dir)
2:  include $(CLEAR_VARS)
3:   
4:  LOCAL_MODULE_TAGS := optional
5:   
6:  # Only compile source java files in this apk.
7:  LOCAL_SRC_FILES := $(call all-java-files-under, src)
8:   
9:  LOCAL_PACKAGE_NAME := Led_demo
10:   
11:  include $(BUILD_PACKAGE)

下面是最终的效果图:

 

完成操作后,在Android源码顶层目录下执行

mmm ./packages/experimental/Tiny4412_led_demo/

然后再执行

./gen-img.sh

将生成的system.img利用MiniTools提供的烧写工具烧写到板子上。

 

最后,附上源代码:

 

完!!

转载地址:http://vhnel.baihongyu.com/

你可能感兴趣的文章
为什么 Cloudera 要创建 Hadoop 安全组件 Sentry ?
查看>>
数学之美:两点之间最快的路径
查看>>
Ansible 详细用法部署安装
查看>>
CPU
查看>>
Spark的这些事&lt;二&gt;——几个概念
查看>>
【知云】第六期:数据级异地容灾如何实现?阿里云帮你打通数据的“任督二脉”...
查看>>
Retrofit2.0使用
查看>>
架构师速成6.4-开发框架
查看>>
lucene 分词相关的类
查看>>
React Native运行原理解析
查看>>
ViewPager通过自定义适配器MyPagerAdapter实现界面导航(上标题)
查看>>
Spring MVC (mvc框架)
查看>>
解开发者之痛:中国移动MySQL数据库优化最佳实践
查看>>
女程序员做了个梦,众网友的神回复
查看>>
PgSQL · 应用案例 · 聚集存储 与 BRIN索引
查看>>
打造高效前端工作环境 - tmux
查看>>
使用阿里云容器监控服务与第三方监控框架集成搭建自己的容器看板
查看>>
PHP time zone unknown Fail
查看>>
[UML]UML系列——用例图中的各种关系(include、extend)
查看>>
oracle v$sysstat性能视图
查看>>