赞
踩
By: fulinux
E-mail: fulinux@sina.com
Blog: https://blog.csdn.net/fulinus
喜欢的盆友欢迎点赞和订阅!
你的喜欢就是我写作的动力!
我们鸿蒙3.2设备上连接了sensor,如accel和gyro,是通过i2c总线连接的,在鸿蒙HDF的设备私有信息配置文件如下描述:
vendor/sprd/uis7885/hdf_config/khdf/sensor/accel/qmi8658_config.hcs
sensorBusConfig :: sensorBusInfo {
busType = 0; // 0:i2c 1:spi
busNum = 2;
busAddr = 0x6b;
regWidth = 1; // 1byte
}
sensorIdAttr :: sensorIdInfo {
chipName = "qmi8658";
chipIdRegister = 0x00;
chipIdValue = 0x05;
}
即总线是i2c2,从设备的sensor地址是0x6b,chip id的寄存器地址是0x00。chip id值是0x5。
我们先研究下如何通过测试程序来操作I2C,读取这个chip id值。
鸿蒙标准系统中,使用的是Linux内核,这个没有官网上的I2C平台驱动中描述的这样需要编写I2C平台驱动。
使用这个I2C平台驱动文件:drivers/hdf_core/adapter/khdf/linux/platform/i2c/i2c_adapter.c
比如获取对应的I2C adapter:
static int LinuxI2cProbe(struct device *dev, void *data) { int32_t ret; struct I2cCntlr *cntlr = NULL; struct i2c_adapter *adapter = NULL; (void)data; if (dev == NULL) { HDF_LOGE("%s: dev is null", __func__); return HDF_ERR_INVALID_OBJECT; } if (dev->type != &i2c_adapter_type) { return HDF_SUCCESS; // continue probe } HDF_LOGI("%s: Enter", __func__); adapter = to_i2c_adapter(dev); //获取i2c adapter cntlr = (struct I2cCntlr *)OsalMemCalloc(sizeof(*cntlr)); if (cntlr == NULL) { HDF_LOGE("%s: malloc cntlr fail!", __func__); i2c_put_adapter(adapter); return HDF_ERR_MALLOC_FAIL; } cntlr->busId = adapter->nr; cntlr->priv = adapter; cntlr->ops = &g_method; ret = I2cCntlrAdd(cntlr); //这个I2C控制器添加到HDF框架中,后面会在I2cOpen函数中调用I2cCntlrGet函数查找到对应的控制器 if (ret != HDF_SUCCESS) { i2c_put_adapter(adapter); OsalMemFree(cntlr); cntlr = NULL; HDF_LOGE("%s: add controller fail:%d", __func__, ret); return ret; } HDF_LOGI("%s: i2c adapter %d add success", __func__, cntlr->busId); return HDF_SUCCESS; }
参考:http://docs.openharmony.cn/pages/v3.2/zh-cn/device-dev/guide/device-driver-demo.md/
上面我们提及to_i2c_adapter添加i2c 适配器,然后又将总线ID、适配器和操作方法等通过I2cCntlrAdd添加到HDF驱动框架中,后面在UHDF或KHDF中通过调用I2cOpen函数,间接调用了I2cCntlrGet函数,在HDF框架中找到对应的总线ID、适配器和操作方法等,然后就可以操作I2C总线了。
I2cCntlrAdd函数:
//drivers/hdf_core/framework/support/platform/src/i2c/i2c_core.c int32_t I2cCntlrAdd(struct I2cCntlr *cntlr) { int32_t ret; if (cntlr == NULL) { return HDF_ERR_INVALID_OBJECT; } if (cntlr->ops == NULL) { HDF_LOGE("I2cCntlrAdd: no ops supplied!"); return HDF_ERR_INVALID_OBJECT; } if (cntlr->lockOps == NULL) { HDF_LOGI("I2cCntlrAdd: use default lock methods!"); cntlr->lockOps = &g_i2cLockOpsDefault; } if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) { HDF_LOGE("I2cCntlrAdd: init lock fail!"); return HDF_FAILURE; } ret = I2cManagerAddCntlr(cntlr); if (ret != HDF_SUCCESS) { (void)OsalMutexDestroy(&cntlr->lock); return ret; } return HDF_SUCCESS; }
I2cOpen函数:
DevHandle I2cOpen(int16_t number)
{
return (DevHandle)I2cCntlrGet(number);
}
I2cCntlrGet函数:
/* * Find an i2c controller by bus number, without ref count */ static struct I2cCntlr *I2cManagerFindCntlr(int16_t number) { struct I2cCntlr *cntlr = NULL; struct I2cManager *manager = g_i2cManager; if (number < 0 || number >= I2C_BUS_MAX) { HDF_LOGE("I2cManagerFindCntlr: invalid busId:%hd!", number); return NULL; } if (manager == NULL) { HDF_LOGE("I2cManagerFindCntlr: get i2c manager fail!"); return NULL; } if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { HDF_LOGE("I2cManagerFindCntlr: lock i2c manager fail!"); return NULL; } cntlr = manager->cntlrs[number]; (void)OsalMutexUnlock(&manager->lock); return cntlr; } /* * Find and return an i2c controller by number, with ref count */ struct I2cCntlr *I2cCntlrGet(int16_t number) { return I2cManagerFindCntlr(number); }
在drivers/hdf_core/framework/support/platform/src/i2c/i2c_core.c文件中,主要就是实现这个上述这些功能
I2C平台驱动既可以为其他HDF驱动提供接口,比如挂接在I2C总线上的sensor驱动,也可以为用户空间提供通用的操作接口。这些接口都是这些:I2cOpen(),I2cClose(),I2cTransfer()。所以可以在drivers/hdf_core/framework/support/platform/src/i2c/中看到有这两个文件:
drivers/hdf_core/framework/support/platform/src/i2c/i2c_if.c
drivers/hdf_core/framework/support/platform/src/i2c/i2c_if_u.c
其中i2c_if.c就是对其他HDF驱动提供接口的:
#include "i2c_if.h" #include "devsvc_manager_clnt.h" #include "hdf_base.h" #include "hdf_log.h" #include "i2c_core.h" #include "osal_mem.h" #include "securec.h" #define HDF_LOG_TAG i2c_if #define I2C_SERVICE_NAME "HDF_PLATFORM_I2C_MANAGER" DevHandle I2cOpen(int16_t number) { return (DevHandle)I2cCntlrGet(number); } void I2cClose(DevHandle handle) { if (handle != NULL) { I2cCntlrPut((struct I2cCntlr *)handle); } } int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count) { if (handle == NULL) { return HDF_ERR_INVALID_OBJECT; } if (msgs == NULL || count <= 0) { HDF_LOGE("I2cTransfer: err params! msgs:%s, count:%hd", (msgs == NULL) ? "0" : "x", count); return HDF_ERR_INVALID_PARAM; } return I2cCntlrTransfer((struct I2cCntlr *)handle, msgs, count); }
其中i2c_if_u.c就是对用户空间提供通用的操作接口:
#include "hdf_base.h"
#include "hdf_io_service_if.h"
#include "hdf_log.h"
#include "i2c_if.h"
#include "i2c_service.h"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。