It's lighting again, no mistake. Learning hardware always starts with lighting, right, but also with Android application.
How to control customized hardware with Android? Use JNI.
1. Preparations
Okay, do some preparations first. Preparations are all about setting up an environment and downloading something. See some links. Order me!
2. led driver
As a matter of fact, I shouldn't post the lighting program, but considering that some students have not learned how to drive Android, I will post it for reference only.
#include <linux/kernel.h> #include <linux/module.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/delay.h> #include <mach/gpio.h> #include <mach/regs-gpio.h> #include <plat/gpio-cfg.h> #define DEVICE_NAME "leds" static int led_gpios[] = { S5PV210_GPJ2(0), S5PV210_GPJ2(1), S5PV210_GPJ2(2), S5PV210_GPJ2(3), }; #define LED_NUM ARRAY_SIZE(led_gpios) static long gec210_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case 0: case 1: if (arg > LED_NUM) { return -EINVAL; } gpio_set_value(led_gpios[arg], !cmd); //printk(DEVICE_NAME": %d %d\n", arg, cmd); break; default: return -EINVAL; } return 0; } static struct file_operations gec210_led_dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = gec210_leds_ioctl, }; static struct miscdevice gec210_led_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &gec210_led_dev_fops, }; static int __init gec210_led_dev_init(void) { int ret; int i; for (i = 0; i < LED_NUM; i++) { ret = gpio_request(led_gpios[i], "LED"); if (ret) { printk("%s: request GPIO %d for LED failed, ret = %d\n", DEVICE_NAME, led_gpios[i], ret); return ret; } s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT); gpio_set_value(led_gpios[i], 1); } ret = misc_register(&gec210_led_dev); printk(DEVICE_NAME"\tinitialized\n"); return ret; } static void __exit gec210_led_dev_exit(void) { int i; for (i = 0; i < LED_NUM; i++) { gpio_free(led_gpios[i]); } misc_deregister(&gec210_led_dev); } module_init(gec210_led_dev_init); module_exit(gec210_led_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GEC Inc.");
Makefile is also attached:
ifneq ($(KERNELRELEASE),) obj-m :=led_drv.o else module-objs :=led_drv.o KERNELDIR :=/home/gec/linux_kernel/linux-2.6.35.7/ PWD :=$(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif clean: $(RM) *.ko *.mod.c *.mod.o *.o *.order *.symvers *.cmd
That linux-2.6.35.7 refers to the Linux kernel version of Android system on GEC210 board, and also has the source code of this kernel under the Linux of PC. The path is put in Makefile, or students who need to change Makefile can download it by themselves.
Okay. After executing make, you can get a file at the end of. ko. Put this. Ko file into the file system of GEC210 board. How to put it in? SD card can also be used, network line nfs can also be used, serial line can also be used. It's not detailed here.
3. Writing Android Applications
Not to mention, look at the code, it is the most basic. 2.2 Edition
LedDemoTestActivity.java
package com.gec.leddemotest.activity; import android.app.Activity; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.Toast; public class LedDemoTestActivity extends Activity { private RadioGroup radioGroupLed01; private RadioGroup radioGroupLed02; private RadioGroup radioGroupLed03; private RadioGroup radioGroupLed04; static{ System.loadLibrary("leddemotest"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); openRunLed(); radioGroupLed01=(RadioGroup)findViewById(R.id.radioGroupLed01); radioGroupLed01.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub if(checkedId==R.id.chooseLed01_1) { startRunLed(0,1); Toast.makeText(LedDemoTestActivity.this, R.string.led1_on, Toast.LENGTH_LONG).show(); }else if(checkedId==R.id.chooseLed01_2) { startRunLed(0,0); Toast.makeText(LedDemoTestActivity.this, R.string.led1_off, Toast.LENGTH_LONG).show(); } } }); radioGroupLed02=(RadioGroup)findViewById(R.id.radioGroupLed02); radioGroupLed02.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub if(checkedId==R.id.chooseLed02_1) { startRunLed(1,1); Toast.makeText(LedDemoTestActivity.this, R.string.led2_on, Toast.LENGTH_LONG).show(); }else if(checkedId==R.id.chooseLed02_2) { startRunLed(1,0); Toast.makeText(LedDemoTestActivity.this, R.string.led2_off, Toast.LENGTH_LONG).show(); } } }); radioGroupLed03=(RadioGroup)findViewById(R.id.radioGroupLed03); radioGroupLed03.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub if(checkedId==R.id.chooseLed03_1) { startRunLed(2,1); Toast.makeText(LedDemoTestActivity.this, R.string.led3_on, Toast.LENGTH_LONG).show(); }else if(checkedId==R.id.chooseLed03_2) { startRunLed(2,0); Toast.makeText(LedDemoTestActivity.this, R.string.led3_off, Toast.LENGTH_LONG).show(); } } }); radioGroupLed04=(RadioGroup)findViewById(R.id.radioGroupLed04); radioGroupLed04.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub if(checkedId==R.id.chooseLed04_1) { startRunLed(3,1); Toast.makeText(LedDemoTestActivity.this, R.string.led4_on, Toast.LENGTH_LONG).show(); }else if(checkedId==R.id.chooseLed04_2) { startRunLed(3,0); Toast.makeText(LedDemoTestActivity.this, R.string.led4_off, Toast.LENGTH_LONG).show(); } } }); } protected void onDestroy() { closeRunLed(); } public native void startRunLed(int whichLed,int on); public native void openRunLed(); public native void closeRunLed(); }
To create a jni file in the project directory, put the following file in it.
appleds.c
#include <android/log.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <jni.h> #define LED_ON 1 #define LED_OFF 0 int fd; JNIEXPORT void JNICALL Java_com_gec_leddemotest_activity_LedDemoTestActivity_openRunLed (JNIEnv *env, jobject this,jint whichLed,jint on) { fd = open("/dev/leds", 0); } JNIEXPORT void JNICALL Java_com_gec_leddemotest_activity_LedDemoTestActivity_startRunLed (JNIEnv *env, jobject this,jint whichLed,jint on) { if (fd < 0) { perror("open device leds"); exit(1); } ioctl(fd, on,whichLed); } JNIEXPORT void JNICALL Java_com_gec_leddemotest_activity_LedDemoTestActivity_closeRunLed (JNIEnv *env, jobject this,jint whichLed,jint on) { close(fd); }
The above JNIEXPORT is necessary, void is the return type, JNICALL is also necessary, and Java is also necessary. Java is followed by the function name called under the LedDemoTestActivity package com.gec.leddemotest.activity, and it is OK to change. to. That's probably what it means. In JNI. C file, so to call the function parameters are at least two, one is JNIEnv *env, the other is jobject this. What is the specific use, you can check JNI online. In addition, parameters like int are written as jint in JNI. Although int is the same as jint, the JNI format is suitable for jint. In JNI. c, all data types used can be added with j. Of course, the header file should be packaged with jni.h.
4. Write Android.mk
Android.mk is an important part of compiling. so files, there are two.
Here's Android.mk in the JNI folder
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libleddemotest a LOCAL_SRC_FILES :=appleds.c b LOCAL_C_INCLUDES += \ c $(JNI_H_INCLUDE) LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY) d
a: Generate the C dynamic library name libleddemotest(JAVA layer intermodulates by loading the library name)
b: Compile C files
c: Load jni library header file
d: Generating libleddemotest dynamic library
Here's Android.mk in the project directory
LOCAL_PATH:= $(call my-dir) a include $(CLEAR_VARS) b LOCAL_SRC_FILES := $(call all-subdir-java-files) c LOCAL_PACKAGE_NAME := LedDemoTest d LOCAL_JNI_SHARED_LIBRARIES := libleddemotest e include $(BUILD_PACKAGE) f include $(LOCAL_PATH)/jni/Android.mk g # Use the folloing include to make our test apk. include $(call all-makefiles-under,$(LOCAL_PATH)) h
a: An Android.mk file must first define LOCAL_PATH to get the current directory
b: Variables used to initialize "LOCAL_XXX" in the Android.mk file
c: Compile Java files
d: Generate Android application apk file name
e: Generate Android application apk file name
f: Generating Android applications
g: Compile Android.mk file in jni directory
h: Compile all Android.mk files in this project
5. Execute ndk-build
Execute in cygwin, use linux command, enter the project directory, and execute ndk-build.
6. Set permissions for leds device files
Connect GEC210 board with serial port line, execute insmod XXXX.ko file, load device file into the kernel, and then there will be a leds device file under / dev.
With chmod 777 leds, increase the device permission of leds, all right. You can run the application on the GEC210 board. Enjoy it.
Source code will be attached later.
Reproduced in: https://my.oschina.net/u/860952/blog/549244