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

news2024/9/28 23:25:57

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

阅读目录(Content)

  • 一、编写驱动程序
  • 二、编写代码测试驱动程序
  • 三、编写HAL代码
  • 四、编写Framework代码
  • 五、编写JNI代码
  • 六、编写App

参考资料:

《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

下面开始:

回到顶部(go to top)

一、编写驱动程序

分析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用户手册》

      回到顶部(go to top)

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

      在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登陆板子,进行测试。

      回到顶部(go to top)

      三、编写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将其烧写到板子上。

      回到顶部(go to top)

      四、编写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类。

    • 回到顶部(go to top)

      五、编写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/

      回到顶部(go to top)

      六、编写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提供的烧写工具烧写到板子上。

      最后,附上源代码:

      基于TINY4412的Andorid开发-------简单的LED灯控制.rar_免费高速下载|百度网盘-分享无限制

      完!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/503541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实时语义分割PIDNet算法TensorRT转换

[PIDNet](GitHub - XuJiacong/PIDNet: This is the official repository for our recent work: PIDNet) 是22年新开源的实时语义分割算法&#xff0c;和DDRNet一样具有不错的性能 网络结构如下&#xff1a; 网络分为三个分支&#xff0c;如上图&#xff0c;整体结构和DDRNet比…

shell 脚本中的函数

目录 一. shell 函数作用&#xff1a;二. shell 函数的定义格式&#xff1a;三.函数返回值&#xff1a;四.函数传参&#xff1a;扩展&#xff1a; 六. 函数变量的作用范围:七 . 递归7.1阶乘 八. 函数库 一. shell 函数作用&#xff1a; 使用函数可以避免代码的重复 使用函数可以…

OJ刷题 第十五篇(递推较多,奥赛篇)

31005 - 昆虫繁殖&#xff08;难度非常大&#xff0c;信息奥赛题&#xff09; 时间限制 : 1 秒 内存限制 : 128 MB 科学家在热带森林中发现了一种特殊的昆虫&#xff0c;这种昆虫的繁殖能力很强。每对成虫过x个月产y对卵&#xff0c;每对卵要过两个月长成成虫。假设每个成虫…

从零开始 Spring Boot 27:IoC

从零开始 Spring Boot 27&#xff1a;IoC 自从开始学习和从事Spring Boot开发以来&#xff0c;一个一直让我很迷惑的问题是IoC和Bean到底是什么东西。这个问题一直到我翻阅完Spring开发文档Core Technologies (spring.io)后才真正得到解惑。 虽然中文互联网上关于IoC的文章很多…

基于AT89C51单片机的电子琴设计与仿真

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87765092?spm1001.2014.3001.5503 源码获取 运用单片机&#xff0c;将音乐的大部分音符与相应按键相匹配&#xff0c;让音乐爱好者利用单片机也可以进行演奏。 基…

SAP EWM /SCWM/CHM_LOG - 显示及分析检查日志

很多公司上了EWM系统后会在运行一段时间之后出现一些系统数据异常情况&#xff0c;问题大致分为以下一些情况&#xff1a; 序号异常情况1 库存调整过账后可用数量的数据不正确2 错误地传输原产国 (2)3 HU 在可用库存中&#xff0c;即使不允许 HU4 非 AQUA 级别创建仓库任务后可…

TCP通讯(三次握手、四次挥手;滑动窗口;TCP状态转换;端口复用;TCP心跳检测机制)

前言&#xff1a;建议看着图片&#xff0c;根据文字描述走一遍TCP通讯过程&#xff0c;加深理解。 目录 TCP通信时序&#xff1a; 1&#xff09;建立连接&#xff08;三次握手&#xff09;的过程&#xff1a; 2&#xff09;数据传输的过程&#xff1a; 3&#xff09;关闭连…

智能优化算法:斑马优化算法-附代码

智能优化算法&#xff1a;斑马优化算法 文章目录 智能优化算法&#xff1a;斑马优化算法1.斑马优化算法1.1 初始化1.2 阶段一&#xff1a;觅食行为1.3 阶段二&#xff1a;针对捕食者的防御策略 2.实验结果3.参考文献4.Matlab 摘要&#xff1a;斑马优化算法&#xff08;Zebra Op…

协同设计有什么优势?都有哪些协同设计软件

设计师创作既有视觉吸引力又实用的作品需要很多时间。对于某些项目&#xff0c;第一次可能会顺利验收&#xff0c;但事实上&#xff0c;设计和修改总是伴随着。 如何有效地修改和促进项目的实施&#xff1f;答案很简单&#xff1a;协作设计。本文将带您深入学习协作设计的相关…

Spring01-Spring简介、IOC简介及入门、IOC详解、bean讲解、依赖注入、配置文件模块化、实现CRUD

Spring简介 一、Spring 是什么 Spring 是一个分层的 Java SE/EE full-stack (一站式) 轻量级开源框架 以 IOC &#xff08;Inverse Of Control:反转控制) 和 AOP &#xff08;Aspect Oriented Programming:面向切面编程) 为核心。 在 Java三层架构中 分别提供了响应技术 分…

docker php安装redis扩展

有这么一个情况&#xff0c;我在docker中&#xff0c;安装了镜像&#xff0c;也启动了容器&#xff0c;容器有&#xff1a;nginx、mysql、redis、php 是一个基本的开发环境 容器启动成功&#xff0c;我们先连接一下&#xff0c;看看是否正常。 先保证这些都ok&#xff0c;我们…

【Spring框架一】——Spring框架简介

系列文章目录 Spring框架简介 系列文章目录前言一、什么是Spring框架&#xff1f;二、Spring框架的优势1.简化开发流程&#xff1a;Spring提供了许多现成的功能&#xff0c;可以使得开发人员在构建应用程序时减少编写重复代码的工作。2.提高可维护性&#xff1a;Spring框架采用…

chatgpt搜索脚本

安装地址 https://greasyfork.org/zh-CN/scripts/459997 注意事项 &#xff01;&#xff01;注意&#xff1a;如果你在360相关浏览器上使用插件。360搜索将不会生效&#xff0c;因为已被浏览器禁用在so.com网址上使用。 &#xff01;&#xff01;尽量选择tampermonkey脚本管…

面试华为测试岗,收到offer后我却毫不犹豫拒绝了....

我大学学的是计算机专业&#xff0c;毕业的时候&#xff0c;对于找工作比较迷茫&#xff0c;也不知道当时怎么想的&#xff0c;一头就扎进了一家外包公司&#xff0c;一干就是2年。我想说的是&#xff0c;但凡有点机会&#xff0c;千万别去外包&#xff01; 在深思熟虑过后&am…

Android性能优化专家需求量大,人才缺口呼之欲出

前言 Android性能优化是Android应用开发中一个非常重要的环节。一款高性能、流畅的应用可以提高用户体验和满意度&#xff0c;提升应用的用户留存率和活跃度。而在今天&#xff0c;移动设备日趋普及&#xff0c;市场竞争日益激烈&#xff0c;优秀的性能已经成为了Android应用不…

Android安卓手机APP应用自有keystore签名证书怎么生成?

Android安卓keystore签名证书怎么生成&#xff1f; 1、安装JRE环境 Oracle官方下载jre安装包&#xff1a;https://www.caochai.com/article-4206.html &#xff0c;并记住安装的目录&#xff1b; 2、打开电脑上的cmd命令提示符工具&#xff0c;先进入jre安装目录&#xff1b…

宿主机(Windos)上文件上传至Ubuntu (linux)

因为我想在ubuntu20.04 上安装Sublime Text ,然而我不想在ubuntu 上下载安装因为太简单了。 我想在windos 上下载好linux 版本&#xff0c;然后发送到ubuntu上&#xff08;和ubuntu上下载安装多了一个上传的过程&#xff09;&#xff0c;我决定挑战一下 第一步进入VM 后打开你…

【Linux学习】多线程——互斥 | 线程安全

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 互斥 | 线程安全 &#x1f969;线程不安全&#x1f35a;线程不安全的原因 &#x1f969;线程互斥…

网络编程五--自定义应用层协议

写在前面 前面回声服务器/客户端介绍了如何通过对收发IO的控制实现回声服务器/客户端。 在服务器端应用层的处理&#xff08;协议&#xff09;可以看作是“回声操作”&#xff0c;即回发客户端发来的消息。而在客户端应用层的处理&#xff08;协议&#xff09;则只是简单显示…

Mysql获取指定时间范围数据

MySQL获取某个时间范围内的数据 TO_DAYS(date)函数。 to_days()&#xff1a;返回从0000年至当前日期的总天数。 目录 1、今天(TO_DAYS()) 2、今天昨天(TO_DAYS()) 3.近7天(DATE_SUB()) 5.本月(DATE_FORMAT()) 6.上一月(PERIOD_DIFF()) 7.本季度 8.上季度 9.本年 ​1…