Back when I was in college playing 51 single-chip computer, the first task of the teacher in the laboratory, is to design a 51 single-chip LED water lamp design, and realize several styles. The second task is to design a 51 microcontroller-based key control led flow lamp style design. Need to design hardware diagram, draw Protel circuit diagram, and design a PCB, to achieve Keil and Proteus of the joint, and then welded circuit board, to achieve its function. At that time do not understand, faith this a momentum, all kinds of Baidu, reading, at that time Guo Tianxiang 51 single-chip video super Fire, so the basic in his book and video learned, cattle, worship.
So, this is mainly about the simplest character drive of the key, by setting the connection to the pin as input, and reading its data register, to determine the key press, and then in the overall story about how the Android app calls the LED and key character device, and to achieve a simple function test (press the button, led lit, press release , led off). The next section, which is also the last section, focuses on some of the mechanisms of timer, interrupt, and competition in the character device. Nonsense a little more, into the subject:
1. Press the simplest driver:
<span style= "FONT-SIZE:14PX;" > #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/ input.h> #include <linux/platform_device.h> #include <linux/miscdevice.h> #include <mach/gpio.h > #include <linux/io.h> #include <mach/hardware.h> #include <linux/delay.h> #include <asm/ irq.h> #include <asm/uaccess.h>static struct class *buttondrv_class;static struct device *buttondrv_class_dev ; int major;volatile unsigned long *gpccon;volatile unsigned long *gpcdat;static int button_drv_open (struct inode *inode, s Truct file *file) {PRINTK (">>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>button_drv_open\n ") *GPCCON &= ~ (0xf< < (2*4)) | (0xf<< (3*4))); *gpccon |= (0<< (2*4) | (0<< (3*4))); return 0;} static int button_drv_read (struct file *filp, char __user *buf, size_t count, loff_t *offp) {PRINTK (">>>>>>>>>>>>>>> ; >>>>>>>>>>>>>>>>>>>>>>button_drv_read\n "); unsigned char k_val[2];int regval;regval = *gpcdat;k_val[0] = (Regval & (1<<2))? 1:0;K_VAL[1] = (Regval & (1<<3))? 1:0;PRINTK ("keyvalue[0]=%02x keyvalue[1]=%02x \ n", k_val[0],k_val[1]); Copy_to_user (buf, K_val, sizeof (K_val)); return sizeof (K_val);} static struct File_operations Button_drv_fops = {. Owner = This_module,. Open = Button_drv_open, . read=button_drv_read,};static int Button_drv_init (void) {PRINTK (">>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>button _drv_init\n "); Gpccon = (volatile unsigned long *) Ioremap (0xe0200080, 8); gpcdat= Gpccon + 1;if (! Gpccon) {Return-eio;} Major = Register_chrdev (0, "ButtoN_drv ", &button_drv_fops); Buttondrv_class = Class_create (This_module, "buttondrv"); Buttondrv_class_dev = Device_create (Buttondrv_class, NULL, MKDEV (Major, 0), NULL, "button"); return 0;} static void Button_drv_exit (void) {PRINTK (">>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>button_drv_exit\n "); unregister _chrdev (Major, "button_drv"); Device_unregister (Buttondrv_class_dev); Class_destroy (Buttondrv_class); Iounmap (Gpccon);} Module_init (Button_drv_init); Module_exit (Button_drv_exit); Module_license ("GPL"); </span><span style= "FONT-SIZE:24PX;" ></span>
A brief description of the demo
Button Here are two, one to Gpc12,gpc13, think of the earliest operation of the 51 single-chip microcomputer, the most simple test button is to do, the pin is set as input, and then read the status of the pin. Here s5pv210 the character device, here also try first.
First of all, the user or the upper-level app, for the function of the key demand, is simply by pressing the key, read the different state of the button, to do something. So, the key is to escalate an event or a message. Of course, different key types, the respective functions will also differ. Here is the most common button.
1. Ioremap: Map Its physical address 2 according to the PIN. Set as input:*gpccon &= ~ ((0xf<< (2*4)) | (0xf<< (3*4))); *gpccon |= (0<< (2*4) | (0<< (3*4)));
3. In the Read function, read the value of the pin dat. Regval = *gpcdat;
K_val[0] = (Regval & (1<<2))? 1:0;
K_VAL[1] = (Regval & (1<<3))? 1:0;
2. Authoring of Jni shared libraries
2.1 Source Code
Button_test.cpp
<span style= "FONT-SIZE:14PX;" > #define LOG_TAG "Rfidserialport" #include "utils/log.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include < ;fcntl.h> #include <termios.h> #include <errno.h> #include <string.h> #includ E <jni.h> #include "button_test.h" #include <ctype.h>static int fd_led=-1;static int Fd_button=-1;jint led_ Open (jnienv *env, Jobject thiz) {LOGE ("Led_open >>>>>>>>>>>>>>>> >>>>>>>>>> ") fd_led = open ("/dev/led ", O_RDWR), if (fd_led < 0) {LOGE (" open fd_ Lederror:%s\n ", Strerror (errno)); return-1;} return 0;} Jint Led_close (jnienv *env, Jobject thiz) {close (fd_led); return 0;} Jint Led_set (jnienv *env, Jobject thiz, Jint State) {if (state==1) write (fd_led, "1", 1), Elsewrite (fd_led, "0", 1); return 0;} Jint Button_open (JnieNV *env, Jobject thiz) {LOGE ("Button_open >>>>>>>>>>>>>>>>>> >>>>>>>> ") Fd_button = open ("/dev/button ", O_RDWR), if (Fd_button < 0) {LOGE (" open fd_ Buttonerror:%s\n ", Strerror (errno)); return-1;} return 0;} Jint Button_close (jnienv *env, Jobject thiz) {close (Fd_button); return 0;} Jint Button_get (jnienv *env, Jobject thiz, Jbytearray State) {LOGE ("Button_get >>>>>>>>> >>>>>>>>>>>>>>>>> "); Jbyte *jstate = env-> Getbytearrayelements (state, NULL); int Reply=-1;char value[2];memset (value,0,2); Reply=read (fd_button,value,2); LOGE ("value[0]=%02x value[1]=%02x", value[0],value[1]); if (reply<0) return-1;memcpy (jstate,value,2);env-> Releasebytearrayelements (state, jstate, 0); return 0;} Static Jninativemethod gmethods[] = {{"Led_open", "() i", (void*) led_open},{"Led_close", "() I", (void*) led_close},{"led _set "," (i) I ", (void*) led_set},{" button_open "," () i ", (void*) button_open},{" Button_close "," () i ", (void*) button_close},{" Button_get "," ([B) i ", (void*) Button_get},}; /* Register Several native methods for one class. *///noticestatic const char *classpathname = "com/example/button_test/buttontest"; static int registernatives (JNIEnv* ENV) {Jclass clazz; Clazz = Env->findclass (classpathname); if (clazz = = NULL) {LOGE ("Native Registration unable to find class '%s '", classpathname); return jni_false; }else{Logi ("Find class sucess"); } if (Env->registernatives (Clazz, Gmethods, sizeof (gmethods)/sizeof (Gmethods[0])) < 0) {LOGE ("Registernat Ives failed for '%s ', classpathname); return jni_false; } return jni_true;} /* * **this is called by the VM when the shared library is first loaded. * */jint jni_onload (javavm* vm, void* reserved) {jint result =-1; jnienv* env = NULL; Logi ("Jni_onload"); if (vm->getenv (void * *) &env, jni_version_1_4)! = Jni_OK) {LOGE ("error:getenv failed"); Goto bail; } if (registernatives (env) = jni_true) {LOGE ("Error:registernatives failed"); Goto bail; } result = Jni_version_1_4;bail:return result;} </span><span style= "FONT-SIZE:18PX;" > </span>
button_test.h
<span style= "FONT-SIZE:14PX;" > #include <jni.h> #ifndef _included_button_test#define _included_button_test#ifdef __cplusplusextern "C" {# Endifjint Led_open (jnienv *env, Jobject thiz); Jint led_close (jnienv *env, Jobject thiz); Jint Led_set (JNIEnv *env, Jobject Thiz,int stat); Jint Button_open (jnienv *env, Jobject thiz); Jint button_close (jnienv *env, Jobject thiz); Jint Button_get ( JNIEnv *env, Jobject thiz,jbytearray State); #ifdef __cplusplus} #endif #endif</span><span style= "font-size : 18px; " ></span>
Android.mk
<span style= "FONT-SIZE:14PX;" >local_path:= $ (call My-dir) include $ (clear_vars) Local_module_tags: = englocal_src_files:= Button_test.cpplocal_ Shared_libraries: = libutils libhardware libdl local_c_includes + = $ (jni_h_include) local_module:= Libbuttontestlocal_prelink_module: = Falseinclude $ (build_shared_library) </span>
2.2 Simple analysis of source code
Recall the previous test led program, you can know, led mainly call three methods, open, write, close, with the button is also three, open, read, close.
Now that native needs to provide 6 methods to the top app, how can it be implemented?
Here you need to know the JNI (Java Native Interface), want to learn more about its mechanism, can see "in-depth understanding of Android Volume" chapter II (if you need some information, you can leave a message). Here is the main way to do, specific principles of things, you need to learn afterwards. In simple terms, JNI is a bridge between native (c, C + +) and Java. At the same time, be sure to pay attention to the rigor of the code, error prone. JNI has both static and dynamic registration methods, which are used for dynamic registration.
Button_test.cpp
First look from the back:
jni_onload: Dynamic registration is used, in the Java call system.loadlibrary method, will call Jni_onload, in this function, the main call registernatives method.
registernatives: 1. Clazz = Env->findclass (Classpathname) This is the associated native and Java class, the main, the path is wrong, after Java loaded So, there will be no way to find the native method error.
2. Env->registernatives (Clazz, Gmethods, sizeof (gmethods)/sizeof (Gmethods[0])) < 0 This is primarily an association of registered functions, Can be connected to establish a always-bidirectional mapping from the native method to the Java class method.
Jninativemethod: This is the method mapping table, where you pay attention to the signature information of the parameter and the return value. See this, the basic framework has come out.
Button_test.h
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
Because this is a C + + code, this part is added to the compatibility problem with C.
Android.mk
The previous section has been introduced, where the include $ (build_shared_library), is to compile the module into a dynamic shared library.
Then, if you compile under the Android environment or the NDK, the libbuttontest.so will be generated.
3 Writing the App
Here there are two main parts, part of the import native function, part call native method.
Buttontest.java
Package Com.example.button_test;import Android.content.context;import Android.util.log;public class ButtonTest { static{system.loadlibrary ("Buttontest");} public native int Led_open ();p ublic native int led_close ();p ublic native int led_set (int. state);p ublic native int button_o Pen ();p ublic native int button_close ();p ublic native int button_get (byte state[]);}
Here System.loadlibrary ("Buttontest"), do not need to writelibbuttontest.so. The following are the native functions in the map table, note the consistency of the parameters and the return values.
Package com.example.button_test; is consistent with the static const char *classpathname = "Com/example/button_test/buttontest" in JNI.
mainactivity. java
Package Com.example.button_test;import Android.support.v7.app.actionbaractivity;import Android.os.Bundle;import Android.util.log;import android.view.menu;import android.view.menuitem;import com.example.button_test. Buttontest;public class Mainactivity extends Actionbaractivity {buttontest test=new buttontest ();//Notice byte state[]= {0,0};int flag=1; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Test.led_open (); Test.button_open (); for (;;) {Test.button_get (state); if (state[1] = = 1 | | state[0] = = 1) {test.led_set (1); flag++; if (flag>20) break; } else {test.led_set (0); flag++; if (flag>20) break; } try {Thread.Sleep (500); } catch (Interruptedexception e) {e.printstacktrace (); }} test.button_close (); Test.led_close (); } @Override Public boolean Oncreateoptionsmenu (Menu menu) {//Inflate the menu, this adds items to the Actio n Bar if it is present. Getmenuinflater (). Inflate (R.menu.main, menu); return true; } @Override public boolean onoptionsitemselected (MenuItem Item) {//Handle Action Bar item clicks here. The action bar would//automatically handle clicks on the Home/up button, so long/As you specify a parent Activity in Androidmanifest.xml. int id = item.getitemid (); if (id = = r.id.action_settings) {return true; } return super.onoptionsitemselected (item); } }
Here's what you need to know about eclipse and how to create a new Android project.
1.import Com.example.button_test. Buttontest; Here import buttontest to Local
2.ButtonTest test=new buttontest (); Defines a buttontest class.
3. Call the native method in the function.
Note: This whole process, it is impossible to write one at a time, where the main use of printing debugging means, for some of the more difficult to solve the problem, it may be necessary to use some tools. The entire process:
1. Put two drive numbers, push Ko to Android device, Insmod load two drivers, and change the permissions of its device node, chmod 777/dev/led && chmod 777 Dev/button, Otherwise, the open method in JNI will fail.
2. Write the JNI library. Push the resulting so library to System/lib, and of course you can put it under your Eclipse Project libs/armeabi/, which is generally recommended under the project.
3. Write the application. Running the application, you can see, press the button light on, release the light off.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
First entry Android drive character device (iii)