硬件平台: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 GPF15
writel(tmp, S3C64XX_GPFCON);
} static int s3c64xx_pwm_open(struct inode *inode, struct file *file)
{
if (!down_trylock(&lock))
return 0;
else
return -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_S3C6410
tristate "pwm"
depends on CPU_S3C6410

make menuconfig配置内核后编译内核

make zImage后启动Android系统

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

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

eclipse建立一个新的应用project。取名为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 { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pwm);
} @Override
public 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 { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pwm);
} @Override
public 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 { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pwm);
} @Override
public 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工具编译生成。 }
}

上述步骤就绪后,编译project,再将该project复制到Ubuntu下

project文件夹下创建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 __cplusplus
extern "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 := pwm
LOCAL_SRC_FILES := pwm.c
LOCAL_LDLIBS := -llog
LOCAL_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,假设project文件夹下没有libs/armeabi,那么就创建armeabi



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

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

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

pwm.apk

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

pm install -f pwm.apk

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

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

最新文章

  1. java基础思维导图
  2. eclipse 启动到loading workbench... 自动关闭
  3. Adaboost\GBDT\GBRT\组合算法
  4. crack a router
  5. [codevs1154][COJ0177][NOIP2006]能量项链
  6. Sublime Text 快捷键及插件安装
  7. Tengine安装配置
  8. StyleCop学习笔记——默认的规则
  9. ORACLE模拟临时文件、日志成员、口令文件丢失情况与恢复【weber出品】
  10. CSS 选择器的学习
  11. iOS开发—— UIImagePickerController获取相册和拍照
  12. c语言的数组
  13. 检测磁盘驱动的健康程度SMART
  14. 【原创】Windows平台下Git的安装与配置
  15. IntelliJ IDEA 2018.3 重大升级,哪些功能打动了你?
  16. 更新node和npm到最新版本
  17. 使用gulp和browser-sync实现浏览器自动刷新
  18. Asp.Net Core 文件上传处理
  19. Android HttpURLConnection源代码分析
  20. eclipse中git更新操作

热门文章

  1. 25.内置API
  2. Spring-MVC:应用上下文webApplicationContext
  3. 洛谷P1919 【模板】A*B Problem升级版(FFT快速傅里叶)
  4. 获取windows版本信息的做法
  5. Android自定义控件简单实现ratingbar效果
  6. UESTC 1599 wtmsb
  7. How Chromium Displays Web Pages: Bottom-to-top overview of how WebKit is embedded in Chromium
  8. django项目所遇问题总结
  9. cogs 1405. 中古世界的恶龙[The Drangon of Loowater,UVa 11292]
  10. [转]C语言字节对齐问题详解