完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
确认物理设备是否已经正常连接,android6.0.1 i2c_detect 可以用,但是android7.1.2 i2c_detect 本人测试无法使用,但是可以看到i2c设备名称如下:
本人案例是按照设备名为:i2c-1 进行硬件连接的。 还需要注意在打开i2c-1设备时,可能会遇到Pemission Denied错误,如若遇到,请从源码根目录下进入system/ core/rootdir目录,打开ueventd.rc 添加一行:/dev/i2c-1 0666 root root ,每个开发板可能书写格式有所不同,请参考改文件内别的设备书写格式! 以下是在android7.1.2 源码目录下添加HAL层i2c 模块的详细步骤: 1.编写HAL层i2c模块的头文件iic.h 在源码根目录下:hardware/libhardware/include/hardware 新建iic.h文件 #ifndef _HARDWARE_IIC_H #define _HARDWARE_IIC_H #include #include #include #include #include __BEGIN_DECLS #define IIC_HARDWARE_MODULE_ID "iic" #define DEVICE_NAME "/dev/i2c-1" #define I2C_RETRIES 0x0701 #define I2C_TIMEOUT 0x0702 #define I2C_RDWR 0x0707 #define I2C_M_TEN 0x0010 #define I2C_M_RD 0x0001 struct iic_module_t { struct hw_module_t common; }; typedef struct iic_device { struct hw_device_t common; int fd; int (*iic_write)(struct iic_device *dev, unsigned int slaveAddr, unsigned int regAddr, unsigned char dataBuf); int (*iic_read)(struct iic_device *dev, unsigned int slaveAddr, unsigned int regAddr, unsigned char *dataBuf); } iic_device_t; static inline int iic_open(const struct hw_module_t* module, iic_device_t** dev) { return module->methods->open(module, IIC_HARDWARE_MODULE_ID, (struct hw_device_t**) dev); } static inline int iic_close(iic_device_t* dev) { return dev->common.close(&dev->common); } __END_DECLS #endif 2.编写HAL层i2c模块的iic.c 在源码目录下:hardware/libhardware/modules 新建iic目录,在该目录下新建iic.c 和 Android.mk 文件 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct i2c_rdwr_ioctl_data iic_data; int ret; static int t613_iic_write(iic_device_t *dev __unused, unsigned int slaveAddr, unsigned int regAddr, unsigned char dataBuf) { iic_data.nmsgs=1; (iic_data.msgs[0]).len = 3; (iic_data.msgs[0]).addr = slaveAddr>>1; (iic_data.msgs[0]).flags = 0; //write (iic_data.msgs[0]).buf = (unsigned char*)malloc(3); (iic_data.msgs[0]).buf[0] = (unsigned char)(regAddr>>8); (iic_data.msgs[0]).buf[1] = (unsigned char)(regAddr); (iic_data.msgs[0]).buf[2] = dataBuf; ALOGE("IIC write HAL: From register %06x write ",regAddr); ALOGE("%04x ",(iic_data.msgs[0]).buf[2]); ret=ioctl(dev->fd,I2C_RDWR,(unsigned long)&iic_data); if(ret<0) ALOGE("IIC HAL write ioctl error."); usleep(3000); return 0; } static int t613_iic_read(iic_device_t *dev __unused, unsigned int slaveAddr, unsigned int regAddr, unsigned char *dataBuf) { iic_data.nmsgs = 2; (iic_data.msgs[0]).addr = slaveAddr >>1; (iic_data.msgs[0]).flags = 0 ; (iic_data.msgs[0]).len = 2; (iic_data.msgs[0]).buf = (unsigned char*)malloc(2); (iic_data.msgs[0]).buf[0] = (unsigned char)(regAddr>>8); (iic_data.msgs[0]).buf[1] = (unsigned char)(regAddr); (iic_data.msgs[1]).addr = slaveAddr >>1; (iic_data.msgs[1]).flags = I2C_M_RD; (iic_data.msgs[1]).len = 1; (iic_data.msgs[1]).buf=(unsigned char*)malloc(1); (iic_data.msgs[1]).buf = dataBuf; ALOGE("IIC read HAL: From register %06x read ",regAddr); ALOGE("%04x ",(iic_data.msgs[1]).buf[0]); ret=ioctl(dev->fd,I2C_RDWR,(unsigned long)&iic_data); if(ret<0) ALOGE("IIC HAL read ioctl error."); usleep(3000); return 0; } static int iic_device_close(hw_device_t *dev) { free(dev); return 0; } static int iic_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { if (strcmp(name, IIC_HARDWARE_MODULE_ID) == 0) { iic_device_t *dev = calloc(1, sizeof(iic_device_t)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0x00010000; // [31:16] major, [15:0] minor dev->common.module = (struct hw_module_t*) module; dev->common.close = iic_device_close; dev->iic_write = t613_iic_write; dev->iic_read = t613_iic_read; *device = &dev->common; if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) { ALOGE("iic Stub hal: failed to open /dev/i2c-1 --"); free(dev); return -EFAULT; }else{ ALOGI("iic Stub hal: open /dev/i2c-1 successfully."); iic_data.nmsgs=2; iic_data.msgs=(struct i2c_msg*)malloc(iic_data.nmsgs*sizeof(struct i2c_msg)); if(!iic_data.msgs){ ALOGE("malloc error."); close(dev->fd); exit(1); } ioctl(dev->fd, I2C_TIMEOUT, 2); ioctl(dev->fd, I2C_RETRIES, 1); } return 0; } else { return -EINVAL; } } /*===========================================================================*/ /* Default iic HW module interface definition */ /*===========================================================================*/ static struct hw_module_methods_t iic_module_methods = { .open = iic_device_open, }; struct iic_module_t HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = 0x0100, // [15:8] major, [7:0] minor (1.0) .hal_api_version = 0x00, // 0 is only valid value .id = IIC_HARDWARE_MODULE_ID, .name = "Default IIC HW HAL", .author = "https://chhjnavy.github.io/", .methods = &iic_module_methods, }, }; LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := iic.default LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := iic.c LOCAL_SHARED_LIBRARIES := liblog libcutils LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) 在源码根目录下:hardware/libhardware/modules 修改Android.mk 添加iic 文件夹名 hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power u***audio audio_remote_submix camera u***camera consumerir sensors vibrator tv_input fingerprint input vehicle thermal vr iic include $(call all-named-subdir-makefiles,$(hardware_modules)) 在源码根目录下执行:mmm hardware/libhardware/modules/iic/ 会对iic 模块进行编译 在源码根目录下产生 out/target/product/rk3288/obj/lib/iic.default.so.toc 3.编写在JNI (Java Native Interface)提供java层与C/C++交互的接口 在源码根目录下:frameworks/base/services/core/jni 1) 新建com_android_server_IICService.cpp,然后需要让Android启动时加载此jni模块 2) 在同目录下修改onload.cpp: 在namespace android中添加一行: int register_android_server_IICService(JNIEnv *env); 3) 在JNI_onLoad方法中添加一行: register_android_server_IICService(env); 4) 在同目录下修改Android.mk: LOCAL_SRC_FILES增加一行: $(LOCAL_REL_DIR)/com_android_server_IICService.cpp #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include #include #include #include #include namespace android { struct iic_device *iic_dev = NULL; static void iic_setVal(JNIEnv* env, jobject clazz, jint slaveAddr, jint regAddr, jint databuf) { if(!iic_dev) { ALOGE("iic JNI: device is not open."); } iic_dev->iic_write(iic_dev,slaveAddr,regAddr,databuf); } static jint iic_getVal(JNIEnv* env, jobject clazz,jint slaveAddr, jint regAddr) { unsigned char data[1] = {0}; iic_dev->iic_read(iic_dev,slaveAddr,regAddr,data); if(!iic_dev) { ALOGE("iic JNI: device is not open."); } return data[0]; } /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/ static ***oolean iic_init(JNIEnv* env, jclass clazz) { iic_module_t *module; int err; err = hw_get_module(IIC_HARDWARE_MODULE_ID,(const struct hw_module_t**)&module); if (err != 0) { ALOGE("Error acquiring iic hardware module: %d", err); return 0; } err = iic_open(&(module->common), &iic_dev); if (err != 0) { ALOGE("Error opening iic hardware module: %d", err); return 0; } ALOGE("iic device is opening..."); return 1; } /*JNI方法表*/ static const JNINativeMethod method_table[] = { {"init_native", "()Z", (void*)iic_init}, {"setVal_native", "(III)V", (void*)iic_setVal}, {"getVal_native", "(II)I", (void*)iic_getVal}, }; /*注册JNI方法*/ int register_android_server_IICService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/IICService", method_table, NELEM(method_table)); } }; 在源码根目录下执行:mmm frameworks/base/services/core/jni 对该模块进行编译 4.编写跨进程访问服务AIDL(Android Interface Definition Language) 在源码根目录下:frameworks/base/core/java/android/os 1)新建IIICService.aidl 文件 2)修改frameworks/base下的Android.mk编译文件,在LOCAL_SRC_FILES中增加 core/java/android/os/IIICService.aidl package android.os; interface IIICService { void setVal(int slaveAddr, int regAddr, int databuf); int getVal(int slaveAddr, int regAddr); } 在源码根目录下执行:mmm frameworks/base 对该模块进行编译 5.编写AIDL(Android Interface Definition Language)具体实现的方法类 在源码根目录下:frameworks/base/services/core/java/com/android/server 1)新建IICService.java文件 package com.android.server; import android.content.Context; import android.os.IIICService; import android.util.Slog; public class IICService extends IIICService.Stub { private static final String TAG = "IICService"; IICService() { init_native(); } public void setVal(int slaveAddr, int regAddr, int databuf) { setVal_native(slaveAddr, regAddr, databuf); } public int getVal(int slaveAddr, int regAddr) { return getVal_native(slaveAddr, regAddr); } private static native boolean init_native(); private static native void setVal_native(int slaveAddr, int regAddr, int databuf); private static native int getVal_native(int slaveAddr, int regAddr); }; 2)修改frameworks/base/services/java/com/android/server下的SystemServer.java 在private void startOtherServices() 添加 try{ Slog.i(TAG, "IIC SERVICE"); ServiceManager.addService("iic", new IICService()); }catch(Throwable e){ Slog.e(TAG, "Failure starting IIC Service", e); } 在源码根目录下执行:mmm frameworks/base/services 对该模块进行编译 6.编写app 用来测试iic 是否通讯正常 在源码根目录下:packages/apps/T613 主程序如下: 完整code 请到:https://download.csdn.net/download/chhjnavy/11389018 下载 package com.example.t613; import android.support.v7.app.ActionBarActivity; import android.os.ServiceManager; import android.os.IIICService; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends ActionBarActivity implements OnClickListener{ private final static String LOG_TAG = "com.example.t613"; private EditText valueText = null; private Button button_read = null; private Button button_write = null; private Button button_clear = null; private IIICService iicService = null; int len = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iicService = IIICService.Stub.asInterface(ServiceManager.getService("iic")); valueText = (EditText)findViewById(R.id.edit_value); button_read = (Button)findViewById(R.id.button_read); button_read.setOnClickListener(this); button_write = (Button)findViewById(R.id.button_write); button_write.setOnClickListener(this); button_clear = (Button)findViewById(R.id.button_clear); button_clear.setOnClickListener(this); Log.i(LOG_TAG, "Activity Created"); String text = "94"; valueText.setText(text); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void onClick(View v) { if(v.equals(button_read)) { try { int val2 = iicService.getVal(0x60,0x2480); valueText.setText(String.valueOf(val2)); } catch (RemoteException e) { Log.e(LOG_TAG, "Remote Exception while reading value from device."); } }else if(v.equals(button_write)) { try { String val = valueText.getText().toString(); iicService.setVal(0x60,0x2471,0x41); iicService.setVal(0x60,0x2480,Integer.valueOf(val)); } catch (RemoteException e) { Log.e(LOG_TAG, "Remote Exception while writing value to device."); } }else if(v.equals(button_clear)) { String text = ""; valueText.setText(text); } } } 为app编写Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) appcompat_dir := ../../../$(SUPPORT_LIBRARY_ROOT)/v7/appcompat/res gridlayout_dir := ../../../$(SUPPORT_LIBRARY_ROOT)/v7/gridlayout/res bitmap_dir := ../../../frameworks/opt/bitmap/res res_dir := res $(appcompat_dir) $(gridlayout_dir) $(bitmap_dir) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir)) #LOCAL_RESOURCE_DIR := $(LOCAL_PATH) LOCAL_PACKAGE_NAME := T613 LOCAL_CERTIFICATE := platform #LOCAL_PRIVATE_PLATFORM_APIS = true #LOCAL_SDK_VERSION := current LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-gridlayout LOCAL_STATIC_JAVA_LIBRARIES += android-support-v13 #LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/appcompat/res #LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/gridlayout/res LOCAL_AAPT_FLAGS := --auto-add-overlay LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat:android.support.v7.gridlayout include $(BUILD_PACKAGE) include $(call all-makefiles-under,$(LOCAL_PATH)) 在源码根目录下执行:mmm packages/apps/T613 对该模块进行编译 7.在源码根目录下执行:make snod 将添加的模块都加载到img中 8.在源码根目录下执行:./mkimage.sh 更新目录rockdev/Image-rk3288 的文件 9.在源码根目录下执行:cd RKTools/linux/Linux_Pack_Firmware/rockdev 进入该目录执行: ./collectImages.sh && ./mkupdate.sh 产生新的update.img 10.在windows 下打开 SpiImageTools.exe 加在update.img,会在当前文件夹下产生bin 档(该工具在源码目录下 RKToolswindows) 11.打开Win32diskImager.exe 将bin 档烧写到SD卡中,然后上电启动RK3288 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1988 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
2490 浏览 1 评论
RK3588 GStreamer调试四路鱼眼摄像头四宫格显示报错
5272 浏览 1 评论
【飞凌嵌入式OK3576-C开发板体验】RKNN神经网络-YOLO图像识别
254 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
1336 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 09:20 , Processed in 0.489781 second(s), Total 43, Slave 36 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号