本文转载自:http://www.cnblogs.com/pengdonglin137/p/3857724.html

基于TINY4412的Andorid开发-------简单的LED灯控制

 

参考资料:

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

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

作者:彭东林

邮箱:pengdonglin137@163.com

平台介绍:

主机: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 <linux/cdev.h>
   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 <linux/kernel.h>
   2:  #include <linux/module.h>
   3:  #include <linux/fs.h>
   4:  #include <linux/slab.h>
   5:  #include <linux/device.h>
   6:   
   7:  #include <asm/io.h>
   8:  #include <asm/uaccess.h>
   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 <stdio.h>
   2:  #include <sys/types.h>
   3:  #include <sys/stat.h>
   4:  #include <fcntl.h>
   5:  #include <stdlib.h>
   6:  #include <sys/ioctl.h>
   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 <hardware/hardware.h>
   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 <hardware/hardware.h>
   4:  #include <hardware/led_demo_hal.h>
   5:   
   6:  #include <fcntl.h>
   7:  #include <errno.h>
   8:   
   9:  #include <utils/Log.h>
  10:  #include <cutils/atomic.h>
  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 <utils/misc.h>
   8:  #include <utils/Log.h>
   9:  #include <hardware/hardware.h>
  10:  #include <hardware/led_demo_hal.h>
  11:   
  12:  #include <stdio.h>
  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://pan.baidu.com/s/1ntwTz1B

完!!

基于TINY4412的Andorid开发-------简单的LED灯控制【转】的更多相关文章

  1. [转] 基于TINY4412的Andorid开发-------简单的LED灯控制

    阅读目录 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源代码情景分析> ...

  2. 基于TINY4412的Andorid开发-------简单的LED灯控制

    参考资料: <Andriod系统源代码情景分析> <嵌入式Linux系统开发完全手册_基于4412_上册> 作者:彭东林 邮箱:pengdonglin137@163.com 平 ...

  3. 【转载】基于TINY4412的Andorid开发-------简单的LED灯控制

    阅读目录(Content) 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源 ...

  4. CC2530 LED灯控制

      有三个寄存器 分别是功能寄存器.方向寄存器.配置寄存器 功能寄存器 通用 I/O口 说的就是一般的I/O口,可以输出高低电平 为外设IO 例如摄像头或者打印机他们具体实现某些功能(拍照或打印文档) ...

  5. android驱动例子(LED灯控制)

    本例子,讲述在android2.1上完全自已开发一个驱动去控制硬件口并写应用测试该驱动,通过这样一个例子,解析android下的驱动开发流程的应用调用流程,可以说是很好的入门引导 要达到的效果:通过a ...

  6. RK3399 友善NanoPC-T4开发板使用sysfs方法控制status LED状态灯-【申嵌视频-RK3399篇】

    实验1:sysfs 操作方法控制NanoPC-T4开发板上LED灯 (status LED状态灯:GPIO0_B5/LED1_OUT)root@NanoPC-T4: cd /sys/class/led ...

  7. 《RT-Thread Studio开发STM32》第一章~第一节《配置STM32H743XIH6点亮LED灯》

    安装RT-Thread Studio后添加相关芯片库文件,打开软件 打开SDK管理界面,安装相关的库文件,本次采用STM32H743XIH6芯片,野火开发板. 新建工程并设置相关的参数 先编译下下载到 ...

  8. 单片机学习(二)开发板LED灯的控制

    目录 开发板上LED灯相关的电路图 点灯 LED闪烁 LED流水灯 其他效果 灯光二进制计数器 进阶版流水灯 开发板上LED灯相关的电路图 这是P2相关7个引脚的电路图,在默认情况下它是直接接着VCC ...

  9. C#与Arduino通过串口通信来控制LED灯的状态

    一.引言 最近摆弄了一段时间的Arduino,发现Arduino做一些电子类项目.监控.机器人.电子玩具比较容易,并且Arduino与.NET程序集成也不难.接下来介绍一个简单的小程序,C#做的一个W ...

随机推荐

  1. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  2. jQuery 事件方法

    事件方法触发器或添加一个函数到被选元素的事件处理程序. 下面的表格列出了所有用于处理事件的 jQuery 方法. 方法 描述 bind() 向匹配元素附加一个或更多事件处理器 blur() 触发.或将 ...

  3. 总结CSS3新特性(Animation篇)

    动画(Animation),是CSS3的亮点.//之一 通过animation属性指定@keyframe来完成关键帧动画; @keyframe用法: @keyframes name { 0% { to ...

  4. Java [leetcode 21]Merge Two Sorted Lists

    题目描述: Merge two sorted linked lists and return it as a new list. The new list should be made by spli ...

  5. Python 基础教程中的问题及解决方案(1)

    1. 在ubuntu中,调用终端时如: f = open('/home/theone/test_input.txt', 'r') 中的txt格式文本不能加后缀 正确的应为:  f = open('/h ...

  6. a 标签的四个伪类

    link        有链接属性时visited    链接地址已被访问过active     被用户激活(在鼠标点击与释放之间发生的事件)hover      其鼠标悬停 <!DOCTYPE ...

  7. 日期时间范围选择插件:daterangepicker使用总结

    分享说明: 项目中要使用日期时间范围选择对数据进行筛选;精确到年月日 时分秒;起初,使用了layui的时间日期选择插件;但是在IIE8第一次点击会报设置格式错误;研究了很久没解决,但能确定不是layu ...

  8. Oracle学习笔记_08_字符串连接

    附录:参考资料 1.Oracle中字符串连接的实现方法 2.SQL指令— CONCAT(字符串连接函数)

  9. jQuery中的自定义插件之----工厂方法(Factory Widget)

    jQuery赋予了我们很强大的插件自定义的功能,可以作为我们的武器库,应用到所有的网页中,使用的语法比较有意思,下面是对它的一些探讨. 遵循以下的原则: 1 IIFE 创建一个jQuery的scope ...

  10. mysql-笔记-numberic 方法 操作符

    DIV 整数除法---结果舍去小数部分, /除法 ---除以0时返回 null值 -减法 % MOD 取模 ---结果为 余数 也可以用于有小数部分的数返回余数,mod(N,0)返回null值 + 加 ...