基于TINY4412的Andorid开发-------简单的LED灯控制【转】
本文转载自:http://www.cnblogs.com/pengdonglin137/p/3857724.html
基于TINY4412的Andorid开发-------简单的LED灯控制
阅读目录(Content)
参考资料:
《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 <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灯控制【转】的更多相关文章
- [转] 基于TINY4412的Andorid开发-------简单的LED灯控制
阅读目录 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源代码情景分析> ...
- 基于TINY4412的Andorid开发-------简单的LED灯控制
参考资料: <Andriod系统源代码情景分析> <嵌入式Linux系统开发完全手册_基于4412_上册> 作者:彭东林 邮箱:pengdonglin137@163.com 平 ...
- 【转载】基于TINY4412的Andorid开发-------简单的LED灯控制
阅读目录(Content) 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源 ...
- CC2530 LED灯控制
有三个寄存器 分别是功能寄存器.方向寄存器.配置寄存器 功能寄存器 通用 I/O口 说的就是一般的I/O口,可以输出高低电平 为外设IO 例如摄像头或者打印机他们具体实现某些功能(拍照或打印文档) ...
- android驱动例子(LED灯控制)
本例子,讲述在android2.1上完全自已开发一个驱动去控制硬件口并写应用测试该驱动,通过这样一个例子,解析android下的驱动开发流程的应用调用流程,可以说是很好的入门引导 要达到的效果:通过a ...
- 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 ...
- 《RT-Thread Studio开发STM32》第一章~第一节《配置STM32H743XIH6点亮LED灯》
安装RT-Thread Studio后添加相关芯片库文件,打开软件 打开SDK管理界面,安装相关的库文件,本次采用STM32H743XIH6芯片,野火开发板. 新建工程并设置相关的参数 先编译下下载到 ...
- 单片机学习(二)开发板LED灯的控制
目录 开发板上LED灯相关的电路图 点灯 LED闪烁 LED流水灯 其他效果 灯光二进制计数器 进阶版流水灯 开发板上LED灯相关的电路图 这是P2相关7个引脚的电路图,在默认情况下它是直接接着VCC ...
- Visual Studio 2022 开发 STM32 单片机 - 环境搭建点亮LED灯
安装VS2022社区版软件 选择基础的功能就好 安装VisualGDB软件(CSDN资源) 按照提示一步一步安装就好 VisualGDB激活软件(CSDN资源) 将如下软件放在VisualGDB的安装 ...
随机推荐
- [转]Selenium-Webdriver系列Python版教程(1)————快速开始
elenium的历史,selenium2与WebDriver的关系本文就不讲了,想了解的同学们百度一下就可以Ok. 本系列教程是以Selenium-WebDriver的Python版本,首先从 ...
- Python+selenium鼠标、键盘事件
鼠标操作 现在的Web产品提供了丰富的鼠标交互方式,例如鼠标右击.双击.悬停.甚至是鼠标拖动等功能,在Webdriver中,将这些关于鼠标操作的方法封装在ActionChains类提供. 1.鼠标右击 ...
- 图的最小生成树——Kruskal算法
Kruskal算法 图的最小生成树的算法之一,运用并查集思想来求出最小生成树. 基本思路就是把所有边从小到大排序,依次遍历这些边.如果这条边所连接的两个点在一个连通块里,遍历下一条边,如果不在,就把这 ...
- SHELL脚本运行的几种方法以及区别
#1 给脚本加上执行权限chmod u+x a.sh, 而后就可以直接用全路径来执行脚本了,比如当前文件夹下用./a.sh,如果如果脚本所在目录在PATH环境变量之中, 则直接用a.sh即可(这和运行 ...
- 使用Navicat进行数据库对比同步
使用Navicat进行数据库对比同步 当有多个数据库时,有时会出现结构或者数据不同步的问题,这时候可以使用navivat工具对比同步( 我的Navicat版本是11.0.17). 参考博客: 岁伏的博 ...
- HDU3549 最大流 裸题
EK算法 时间复杂度o(n*m*m) 因为有反向边每次bfs时间为 n*m 每次删一条边 最多m次 代码 #include<iostream> #include<string.h& ...
- Python的描述符
1.描述符的定义 描述符是与特定属性互相绑定的一种协议,通过方法被触发修改属性,这些方法包括__get__(),__set__(),__delete__().将这些方法定义在类中,即可实现描述符 2. ...
- Javascript标准事件模型
本文为原创,转载请注明出处: cnzt 文章:cnzt-p http://www.cnblogs.com/zt-blog/p/6676913.html 1. 分类 IE -- 冒泡型 现代 ...
- Eclipse中git插件导入远程库和上传项目源代码到远程库
陆陆续续,从github,csdn的code.之前实习的小公司也是用git管理.发如今版本号控制方面确实比較方便.代码一敲完 . 自己由于完毕了新功能.加入一个新分支.然后提交上去,这就是程序猿一天干 ...
- jquery全局变量---同步请求设置
1.同步 $.ajaxSetup({ async: false }); 2.异步 $.ajaxSetup({ async: true }); 3.说明:我们一般使用同步完要恢复异步.由于js默 ...