RTC(JNI)概述

来源:互联网 发布:网络经典小说排行榜 编辑:程序博客网 时间:2024/05/22 02:15

主要内容

  • RTC概述
  • RTC(JNI)测试从上层AP到底层驱动的流程
  • 如何创建JNI上层AP
  • Eclipse创建一个JNI程序过程
  • Android Studio创建一个JNI程序过程
  • RTC(JNI)AP代码介绍
  • 底层RTC代码介绍
  • Android4.*版本和5.*以后JNI操作底层的差异


 

RTC概述

定义:

英文全称:Real-time clock,中文名称:实时时钟,是指可以像时钟一様输

出实际时间的电子设备,一般会是集成电路,因此也称为时钟芯片。实时时钟芯

片可以为我们提供精确的实时时间,或者为电子系统提供精确的时间基准。  RTC可

以提供稳定的时钟信号给后续电路用。一个没有实时时钟的系统也可以计算实际 时间,通俗的讲就是:时间校准

 

优点:

1)消耗功率低(当使用辅助电源时格外重要)

2)让主系统处理更需时效性的工作

3)有时会比其他方式的输出要更准确


 

实时时钟一般会有备用电源,当主电源断电或 无法使用时,实时时钟可利用备用电源来继 续计算时间,后备电源有两种:

1.超级电容 在充电完后,在主板没有外围电源的情况

下,可以维持大概3天左右的时间。

 

 

 

2.纽扣电池 可以理解为电池,RTC电路专用电池,和超

级电容比可以维持较长一段时间


 

 

RTC(JNI)测试从上层AP到底层驱动的流程

 

  • 流程架构


如何创建JNI上层AP

Eclipse创建一个JNI程序过程

1)下载NDK开发环境(前提是Android开发环境已经准备就绪)

 

官方下载地址ndk_r15b (June 2017) : https://dl.google.com/android/repository/android-ndk-r15b-windows-x86_64.zip 公司下载:

     \\192.168.1.9\share\常用工具 软件\android-ndk-r13b-windows-x86_64.zip

2) 关联eclipse并创建一个测试demo

eclipse导入demo D:\android-ndk-r10e\samples\hello-jni

 

bitmap-plasma

如何在NDK中使用bitmap的例子,早期的NDK版本不能直接使用bitmap,后来的版本中增加了对bitmap的支持。

hello-gl2

在NDK中如何使用OpenGLES的运用

hello-jni

最基本的NDK使用方式,通过NDK获取字符串然后在Android应用中显示出来

hello-neon

在NDK中有关neon的优化

module-exports

多个库的调用方式。foo被编译为静态库,bar被编译为动态库并调用了库foo,zoo被编译为动态库并调用了库bar。

native-activity

完全用NDK实现整个Android程序

native-audio

在NDK中有关音频的操作

native-media

在NDK中对视频的操作

native-plasma

完全用NDK实现整个Android程序并且提供了涉及plasma的优化

san-angeles

移植到Android平台的OpenGL ES的例子

test-libstdc++

对C++的支持,但并非支持C++的全部特征

two-libs

两个库的使用,first为静态库,second为动态库,并且second库调用first库


3) Demo代码结构介绍

 

 


  • public native String  stringFromJNI();

 

  • public native String unimplementedStringFromJNI();

 

  • static { System.loadLibrary("hello-jni"); }

 

 

 

 

 

 

.Java 文件和 .C文件的方法要一一对应


LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE     := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)

 

 

APP_ABI := all

或者

APP_ABI := armeabi-v7a arm64-v8a


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,jobject thiz) {

}


Android StudioJNI


 

RTC(JNI)AP代码介绍

RTC,测试AP主要功能:读取和设置 RTC时间 读取和设置RTC 时钟时间

 

MainActivity.java

 

 

public class MainActivity extends Activity {

// Used to load the 'native-lib' library on application startup.

static {

System.loadLibrary("native-lib");

}

…………………….

//public native void setRTC(int year, int mon, int day, int hour, int min, int sec);

public native void setRTC(String s);

public native String readRTC();

 

public native void setRTCALARM(String s);

public native String readRTCALARM();

 

 

 

 

native-lib.cpp 必定要有与之对应的4个结构体(方法), 并被编译生成 native-lib.so 文件


 

native-lib.cpp


Java_com_xctx_testrtc_MainActivity_setRTC(JNIEnv *env, jobject thiz, jstring jstr)

{


 

 

Java_com_xctx_testrtc_MainActivity_readRTC(JNIEnv *env,jobject thiz) {

 

int i;

int len;

int fd;

RTC_Date rtcDate;

char buf[128];

 

fd = open("/dev/rtc0", O_RDWR);

if (fd < 0) {

LOGI("%s", "open error");

}

 

for (i = 0; i < 18; i++) {

 

len = ioctl(fd, READ_RTC_CMD, (unsigned long)&rtcDate);

if (len < 0) {

LOGI("read error");

}

}

buf[len] = '\0';

sprintf(buf, "%d-%d-%d-%d-%d-%d", rtcDate.rtcDateTime.RTC_Year, rtcDate.rtcDateTime.RTC_Month, rtcDate.rtcDateTime.RTC_Date, rtcDate.rtcDateTime.RTC_Hours, rtcDate.rtcDateTime.RTC_Minutes, rtcDate.rtcDateTime.RTC_Seconds);

 

LOGI("read rtc = %s\n", buf);

close(fd);

return env->NewStringUTF(buf);

}


int i = 0;

int len;

int fd;

RTC_Date rtcDate;

char *buf = Jstring2str(env, jstr);

int year; int mon; int day; int hour; int min; int sec;

//表示现在是set rtc

set_flags = 0;

    sscanf(buf, "%d-%d-%d-%d-%d-%d", &year, &mon, &day, &hour, &min, &sec);

rtcDate.rtcDateTime.RTC_Year = year; rtcDate.rtcDateTime.RTC_Month = mon; rtcDate.rtcDateTime.RTC_Date = day; rtcDate.rtcDateTime.RTC_Hours = hour; rtcDate.rtcDateTime.RTC_Minutes = min; rtcDate.rtcDateTime.RTC_Seconds = sec;

LOGI("%d-%d-%d-%d-%d-%d", year, mon, day, hour, min, sec);

fd = open("/dev/rtc0", O_RDWR);

if (fd < 0) {

LOGI("%s", "open error");

}

rtcDate.cmd = 1;

len = write(fd, &rtcDate, sizeof(RTC_Date));

if (len < 0) {

LOGI("write error");

}

for (i = 0; i < 9; i++) {

len = ioctl(fd, READ_RTC_CMD, (unsigned long)&rtcDate);

if (len < 0) {

LOGI("read error");

}

} close(fd); return;


}


 

 

native-lib.cpp

 

 

 

Java_com_xctx_testrtc_MainActivity_readRTCALARM(JNIEnv *env,jobject thiz) {

int i;

int len;

int fd;

RTC_Date rtcDate;

char buf[128];

 

fd = open("/dev/rtc0", O_RDWR);

if (fd < 0) {

LOGI("%s", "open error");

}

for (i = 0; i < 18; i++) {

memset(&rtcDate, 0, sizeof(RTC_Date));

len = read(fd, &rtcDate, sizeof(RTC_Date));

if (len < 0) {

LOGI("read error");

}

}

 

LOGI("read rtc %d, %d, %d, %d", rtcDate.rtcDateTime.RTC_Date, rtcDate.rtcDateTime.RTC_Hours, rtcDate.rtcDateTime.RTC_Minutes, rtcDate.rtcDateTime.RTC_Seconds);

 

sprintf(buf, "%d-%d-%d-%d", rtcDate.rtcDateTime.RTC_Date, rtcDate.rtcDateTime.RTC_Hours, rtcDate.rtcDateTime.RTC_Minutes, rtcDate.rtcDateTime.RTC_Seconds);

LOGI("read rtc = %s\n", buf);

close(fd);

return env->NewStringUTF(buf);

}


Java_com_xctx_testrtc_MainActivity_setRTCALARM(JNIEnv *env,jobject thiz, jstring jstr)

{

int i = 0; int len; int fd;

RTC_Date rtcDate;

char *buf = Jstring2str(env, jstr);

int year = 1; int mon = 1; int day ;

int hour;

int min;

int sec; //表示现在是set rtc alarm

set_flags = 1;

    sscanf(buf, "%d-%d-%d-%d", &day, &hour, &min, &sec); rtcDate.rtcDateTime.RTC_WeekDay = 1; rtcDate.rtcDateTime.RTC_Year = year; rtcDate.rtcDateTime.RTC_Month = mon; rtcDate.rtcDateTime.RTC_Date = day; rtcDate.rtcDateTime.RTC_Hours = hour; rtcDate.rtcDateTime.RTC_Minutes = min; rtcDate.rtcDateTime.RTC_Seconds = sec;

LOGI("%d-%d-%d-%d-%d-%d", year, mon, day, hour, min, sec);

fd = open("/dev/rtc0", O_RDWR);

if (fd < 0) {

LOGI("%s", "open error");

}

rtcDate.cmd = 2;

len = write(fd, &rtcDate, sizeof(RTC_Date));

if (len < 0) {

LOGI("write error");

}

for (i = 0; i < 7; i++) {

len = ioctl(fd, READ_RTC_ALARM_CMD, (unsigned long)&rtcDate);

if (len < 0) {

LOGI("read error");

}

} close(fd); return;

}


RTC

 

Appnative-lib.cpp: Idevl                                                                cO

 


底层RTC代码介绍

创建RTC设备节点

 

 

1.创建RTC设备驱动

path:alps\mediatek\kernel\drivers\xrtc\rtc_driver.c alps\mediatek\kernel\drivers\xrtc\rtc.h

 

 

 

 

2.使能编译到RTC驱动

在alps\mediatek\kernel\drivers\Makefile

 

 

 

 

  1. 对设备节点权限初始化

在 alps\mediatek\config\mt6582\init.rc


底层RTC代码介绍

驱动函数实现了,init、exit、probe、remove 作为字符设备 的同时还实现了操作字符设备open、release、read、write、 ioctr()等。

(Linux驱动模型)

 

 

static int rtc_remove(struct i2c_client *client)

{  printk("rtc : %s\n",    func   );

return 0; }

 

static const struct i2c_device_id rtc_ids[] = {

{ "rtc0", D_RTC_DEVICE_ADDR, },

{ /* LIST END */ }


#include <linux/init.h>

.......

//打开字符设备

static int rtc_open(struct inode *inode, struct file *file)

{  printk("rtc : hello %s\n",    func   ); return 0;}

 

//释放字符设备

static int rtc_release(struct inode *inode, struct file *file)

{  printk("rtc : hello %s\n",    func   );return 0;}

 

//对字符设备的操作

static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{printk("hello rtc : ioctl function : cmd = %d\n", cmd);

switch(cmd){case READ_RTC_CMD:break;

case READ_RTC_ALARM_CMD:break;}

len = copy_to_user((void *)arg, &rtcDate, sizeof(RTC_Date));

return len;}

//对字符设备的读操作

ssize_t rtc_read(struct file *fp, char    user *buf, size_t count, loff_t * off)

{ len = copy_to_user(buf, &rtcDate, sizeof(RTC_Date));return len; }


};

 

static struct i2c_driver rtc_driver = {

.driver = {.name = "rtc0",},

.probe = rtc_probe,

.remove = rtc_remove,

.id_table = rtc_ids,


//对字符设备的写操作

ssize_t rtc_write(struct file *fp, const char    user *buf, size_t count, loff_t *off)

{ret = RTC_SetDateTime(rtcDateTime); printk("hello rtc : wirte function : ret = %d\n", ret); return len;

}


};

 

static struct i2c_board_info    initdata i2c_rtc_info = { I2C_BOARD_INFO( "rtc0", D_RTC_DEVICE_ADDR)

};

 

static int    init rtc_init(void)

{  XXXXXXXXX

return 0;    }

static void    exit rtc_exit(void)

{ XXXXXXXXx }

 

module_init(rtc_init); module_exit(rtc_exit); MODULE_LICENSE("GPL");


//声明

static struct file_operations rtc_fops = {

.owner = THIS_MODULE,

.open = rtc_open,

.read = rtc_read,

.write = rtc_write,

.release = rtc_release,

.unlocked_ioctl = rtc_ioctl,};

 

//创建设备属性文件

static int rtc_probe(struct i2c_client *client, const struct i2c_device_id *id)

{    int ret;

printk("rtc : %s\n",    func   );}


Android4.2.*版本和4.4.*以后JNI操作底层的差异

 

 

 

为什么会有差异?,Android在4.3的时候引入 SeLinux防火墙,这个时候就算有设备节点和 设备节点的权限是不能操作 这个 设备节点,由此还得适应SeLinux防火墙的规则

 

 

 

 

具体用法参考文档:从底层驱动 到上层APP的流程(2)