硬件平台:S3C6410

操作系统:Ubuntu、windows

板子系统:Android

开发工具:jdk,ndk,eclipse

本次测试从linux内核模块编译开始,以S3C6410的pwm驱动为例。

pwm_6410.c:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/clk.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/miscdevice.h>#include <linux/interrupt.h>#include <plat/regs-timer.h>#include <plat/gpio-cfg.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/mach/time.h>#include <asm/uaccess.h>#include <mach/map.h>#include <mach/regs-clock.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <mach/gpio-bank-e.h>#include <mach/gpio-bank-f.h>#include <mach/gpio-bank-k.h>#include <mach/regs-irq.h>#define DEVICE_NAME  "pwm"static struct semaphore lock;static void PWM_Set_Freq( unsigned long freq ){unsigned long tcon;unsigned long tcnt;unsigned long tcfg1;unsigned long tcfg0;unsigned long pclk;unsigned tmp;struct clk *clk_p;    printk ("Freq is %d",freq);tmp = readl(S3C64XX_GPFCON);//PWM GPF15    tmp &= ~(0x3U << 30);// Timer1    tmp |=  (0x2U << 30);writel(tmp, S3C64XX_GPFCON);tcon  = __raw_readl(S3C_TCON);tcfg1 = __raw_readl(S3C_TCFG1);tcfg0 = __raw_readl(S3C_TCFG0);tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK;tcfg0 |= (50 - 1);     tcfg1 &= ~S3C_TCFG1_MUX1_MASK;    tcfg1 |= S3C_TCFG1_MUX1_DIV16;__raw_writel(tcfg1, S3C_TCFG1);__raw_writel(tcfg0, S3C_TCFG0);clk_p = clk_get(NULL, "pclk");pclk  = clk_get_rate(clk_p);tcnt  = (pclk/50/16)/freq;__raw_writel(tcnt, S3C_TCNTB(1));__raw_writel(tcnt/2, S3C_TCMPB(1));tcon &= ~(0xf << 8);tcon |= (0xb << 8);__raw_writel(tcon, S3C_TCON);tcon &= ~(2 << 8);__raw_writel(tcon, S3C_TCON);}void PWM_Stop( void ){unsigned tmp;tmp = readl(S3C64XX_GPFCON);tmp &= ~(0x3U << 30);// set GPF15writel(tmp, S3C64XX_GPFCON);}static int s3c64xx_pwm_open(struct inode *inode, struct file *file){if (!down_trylock(&lock))return 0;elsereturn -EBUSY;}static int s3c64xx_pwm_close(struct inode *inode, struct file *file){up(&lock);return 0;}static long s3c64xx_pwm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg){switch (cmd) {case 1:if (arg == 0)return -EINVAL;PWM_Set_Freq(arg);break;case 0:PWM_Stop();break;}return 0;}static struct file_operations dev_fops = {    .owner= THIS_MODULE,    .open= s3c64xx_pwm_open,    .release= s3c64xx_pwm_close,     .unlocked_ioctl= s3c64xx_pwm_ioctl,};static struct miscdevice misc = {    .minor = MISC_DYNAMIC_MINOR,    .name  = DEVICE_NAME,    .fops  = &dev_fops,};static int __init dev_init(void){int ret;init_MUTEX(&lock);ret = misc_register(&misc);printk (DEVICE_NAME"\tinitialized\n");    return ret;}static void __exit dev_exit(void){misc_deregister(&misc);}MODULE_LICENSE("GPL");module_init(dev_init);module_exit(dev_exit);
Makefile添加:

obj-$(CONFIG_PWM_S3C6410)        += pwm_6410.o
Kconfig添加:

config PWM_S3C6410tristate "pwm"depends on CPU_S3C6410

make menuconfig配置内核后编译内核

make zImage后启动Android系统

ls /dev会看到名称为pwm的设备驱动

驱动已经加载好,这时候就要编写Android下的测试程序。JNI是Java Native Interface的缩写,即Java本地调用,它允许java代码和其他语言写的代码进行交互。写测试程序时使用JNI方式实现。

eclipse建立一个新的应用工程,取名为pwm,包名为com.example.pwm

默认生成的java代码:PwmActivity.java

package com.example.pwm;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;public class PwmActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pwm);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.activity_pwm, menu);return true;}}
添加本地方法:

package com.example.pwm;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;public class PwmActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pwm);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.activity_pwm, menu);return true;}       public static native int pwm_set_freq(int i, int j);static {  System.loadLibrary("pwm");  // 添加 C/C++动态库导入方法  }}

编辑res/layout下activity_pwm.xml

添加button控件

    <Button        android:id="@+id/pwm_on"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_above="@+id/textView1"        android:layout_alignLeft="@+id/textView1"        android:layout_marginBottom="39dp"        android:onClick="onPwmOnClicked"        android:text="@string/pwm" />
编辑res/values下strings.xml

添加

<string name="pwm">pwm</string>
PwmActivity.java中添加:

    public void onPwmOnClicked(View v){    pwm_set_freq(1,200);    }
PwmActivity.java:

package com.example.pwm;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;public class PwmActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pwm);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.activity_pwm, menu);return true;}        public void onPwmOnClicked(View v){            pwm_set_freq(1,200); //按下按键就输出波形        }public static native int pwm_set_freq(int i, int j);static {  System.loadLibrary("pwm");  // 添加 C/C++动态库导入方法  ,这个库需要使用NDK工具编译生成。}  }
上述步骤就绪后,编译工程,再将该工程拷贝到Ubuntu下

工程目录下创建jni文件夹:


使用javah命令生成jni头文件

注意冒号后没有空格

生成的头文件:


com_example_pwm_PwmActivity.h:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_pwm_PwmActivity */#ifndef _Included_com_example_pwm_PwmActivity#define _Included_com_example_pwm_PwmActivity#ifdef __cplusplusextern "C" {#endif#undef com_example_pwm_PwmActivity_MODE_PRIVATE#define com_example_pwm_PwmActivity_MODE_PRIVATE 0L#undef com_example_pwm_PwmActivity_MODE_WORLD_READABLE#define com_example_pwm_PwmActivity_MODE_WORLD_READABLE 1L#undef com_example_pwm_PwmActivity_MODE_WORLD_WRITEABLE#define com_example_pwm_PwmActivity_MODE_WORLD_WRITEABLE 2L#undef com_example_pwm_PwmActivity_MODE_APPEND#define com_example_pwm_PwmActivity_MODE_APPEND 32768L#undef com_example_pwm_PwmActivity_MODE_MULTI_PROCESS#define com_example_pwm_PwmActivity_MODE_MULTI_PROCESS 4L#undef com_example_pwm_PwmActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define com_example_pwm_PwmActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef com_example_pwm_PwmActivity_BIND_AUTO_CREATE#define com_example_pwm_PwmActivity_BIND_AUTO_CREATE 1L#undef com_example_pwm_PwmActivity_BIND_DEBUG_UNBIND#define com_example_pwm_PwmActivity_BIND_DEBUG_UNBIND 2L#undef com_example_pwm_PwmActivity_BIND_NOT_FOREGROUND#define com_example_pwm_PwmActivity_BIND_NOT_FOREGROUND 4L#undef com_example_pwm_PwmActivity_BIND_ABOVE_CLIENT#define com_example_pwm_PwmActivity_BIND_ABOVE_CLIENT 8L#undef com_example_pwm_PwmActivity_BIND_ALLOW_OOM_MANAGEMENT#define com_example_pwm_PwmActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef com_example_pwm_PwmActivity_BIND_WAIVE_PRIORITY#define com_example_pwm_PwmActivity_BIND_WAIVE_PRIORITY 32L#undef com_example_pwm_PwmActivity_BIND_IMPORTANT#define com_example_pwm_PwmActivity_BIND_IMPORTANT 64L#undef com_example_pwm_PwmActivity_BIND_ADJUST_WITH_ACTIVITY#define com_example_pwm_PwmActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef com_example_pwm_PwmActivity_CONTEXT_INCLUDE_CODE#define com_example_pwm_PwmActivity_CONTEXT_INCLUDE_CODE 1L#undef com_example_pwm_PwmActivity_CONTEXT_IGNORE_SECURITY#define com_example_pwm_PwmActivity_CONTEXT_IGNORE_SECURITY 2L#undef com_example_pwm_PwmActivity_CONTEXT_RESTRICTED#define com_example_pwm_PwmActivity_CONTEXT_RESTRICTED 4L#undef com_example_pwm_PwmActivity_RESULT_CANCELED#define com_example_pwm_PwmActivity_RESULT_CANCELED 0L#undef com_example_pwm_PwmActivity_RESULT_OK#define com_example_pwm_PwmActivity_RESULT_OK -1L#undef com_example_pwm_PwmActivity_RESULT_FIRST_USER#define com_example_pwm_PwmActivity_RESULT_FIRST_USER 1L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_DISABLE#define com_example_pwm_PwmActivity_DEFAULT_KEYS_DISABLE 0L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_DIALER#define com_example_pwm_PwmActivity_DEFAULT_KEYS_DIALER 1L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_SHORTCUT#define com_example_pwm_PwmActivity_DEFAULT_KEYS_SHORTCUT 2L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_LOCAL#define com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L/* * Class:     com_example_pwm_PwmActivity * Method:    pwm_set_freq * Signature: (II)I */JNIEXPORT jint JNICALL Java_com_example_pwm_PwmActivity_pwm_1set_1freq  (JNIEnv *, jclass, jint, jint);#ifdef __cplusplus}#endif#endif

将头文件拷贝到jni目录下,jni目录下创建pwm.c:

#include <jni.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <android/log.h> #define LOG_TAG "PWM" //android logcat #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__ ) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS_ _) jint JNICALL Java_com_example_pwm_PwmActivity_pwm_1set_1freq(JNIEnv *env, jclass thiz, jint cmd, jint freq)  { //函数名与头文件中的保持一致int fd;fd = open("/dev/pwm",O_RDWR);if (fd < 0){printf ("Open /dev/pwm file error\n");return -1;}ioctl(fd,1,200);close (fd);return 0;}

jni目录下创建Android.mk

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := pwmLOCAL_SRC_FILES := pwm.cLOCAL_LDLIBS := -llogLOCAL_C_INCLUDES := $(MY_ANDROID_SOURCE)/frameworks/base/core/jni/android/graphics \$(MY_ANDROID_SOURCE)/external/skia/include/core \$(MY_ANDROID_SOURCE)/external/skia/include/images \$(MY_ANDROID_SOURCE)/frameworks/base/include \$(MY_ANDROID_SOURCE)/system/core/include include $(BUILD_SHARED_LIBRARY)
命令ndk-build,如果工程目录下没有libs/armeabi,那么就创建armeabi


生成了libpwm.so就是我们在Android应用工程中需要的库文件

 static {        System.loadLibrary("pwm");  // 添加 C/C++动态库导入方法        }  

将含有libpwm.so的工程文件从Ubuntu中考到windows,eclipse打开工程,编译生成apk

pwm.apk

在板子上安装,控制终端下输入命令:

pm install -f pwm.apk

安装成功提示success之后,点开软件,点击pwm按钮。

示波器输出200Hz百分之五十的波形,测试成功。


更多相关文章

  1. Android初级教程_获取Android控件的宽和高
  2. Android(安卓)Test(未完工)
  3. android sdk 编译相关
  4. android 4.1 UI 工具测试的新利器, uiautomator
  5. appium自动化测试总结(转载liangww)
  6. android 命令行 sqlite3 not found 解决方案
  7. ubuntu下android源代码以及内核的获取
  8. 使用Android(安卓)Studio遇到的一些常见问题总结
  9. android工程中,各种类型的资源文件

随机推荐

  1. TextView中ellipsize属性焦点异常处理
  2. 如何为香蕉派 banana pi BPI-M2编译Andro
  3. android菜单Tips
  4. Android 编程设置 APN
  5. [android]Activity切换动画
  6. Android(安卓)EGL_BAD_CONFIG error,配置E
  7. Android适配器之-----SimpleAdapter
  8. Android UI开发第二篇——多级列表(Expand
  9. android布局学习利器-Hierarchy Viewer
  10. Android中/system/build.prop文件解读